Skip to content

Integrate "Target-specific code" (ocsigen/js_of_ocaml#1655) #85

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

Merged
merged 9 commits into from
Oct 2, 2024
Merged
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 compiler/bin-js_of_ocaml/build_fs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ function jsoo_create_file_extern(name,content){
let pfs_fmt = Pretty_print.to_out_channel chan in
let (_ : Source_map.t option) =
Driver.f
~target:(JavaScript pfs_fmt)
~standalone:true
~wrap_with_fun:`Iife
~link:`Needed
~formatter:pfs_fmt
(Parse_bytecode.Debug.create ~include_cmis:false false)
code
in
Expand Down
3 changes: 2 additions & 1 deletion compiler/bin-js_of_ocaml/check_runtime.ml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ let print_groups output l =
output_string output (Printf.sprintf "%s\n" name)))

let f (runtime_files, bytecode, target_env) =
Generate.init ();
Config.set_target `JavaScript;
Linker.reset ();
let runtime_files, builtin =
List.partition_map runtime_files ~f:(fun name ->
match Builtins.find name with
Expand Down
17 changes: 7 additions & 10 deletions compiler/bin-js_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ let output_gen ~standalone ~custom_header ~build_info ~source_map output_file f
let data = Source_map.to_string sm in
"data:application/json;base64," ^ Base64.encode_exn data
| Some output_file ->
Source_map.to_file sm ~file:output_file;
Source_map.to_file sm output_file;
Filename.basename output_file
in
Pretty_print.newline fmt;
Expand Down Expand Up @@ -91,6 +91,7 @@ let run
} =
let include_cmis = toplevel && not no_cmis in
let custom_header = common.Jsoo_cmdline.Arg.custom_header in
Config.set_target `JavaScript;
Jsoo_cmdline.Arg.eval common;
Generate.init ();
(match output_file with
Expand Down Expand Up @@ -184,7 +185,7 @@ let run
let init_pseudo_fs = fs_external && standalone in
let sm =
match output_file with
| `Stdout, fmt ->
| `Stdout, formatter ->
let instr =
List.concat
[ pseudo_fs_instr `create_file one.debug one.cmis
Expand All @@ -194,15 +195,15 @@ let run
in
let code = Code.prepend one.code instr in
Driver.f
~target:(JavaScript fmt)
~standalone
?profile
~link
~wrap_with_fun
?source_map
~formatter
one.debug
code
| `File, fmt ->
| `File, formatter ->
let fs_instr1, fs_instr2 =
match fs_output with
| None -> pseudo_fs_instr `create_file one.debug one.cmis, []
Expand All @@ -218,12 +219,12 @@ let run
let code = Code.prepend one.code instr in
let res =
Driver.f
~target:(JavaScript fmt)
~standalone
?profile
~link
~wrap_with_fun
?source_map
~formatter
one.debug
code
in
Expand Down Expand Up @@ -282,7 +283,7 @@ let run
then (
let prims = Linker.list_all () |> StringSet.elements in
assert (List.length prims > 0);
let code, uinfo = Parse_bytecode.predefined_exceptions ~target:`JavaScript in
let code, uinfo = Parse_bytecode.predefined_exceptions () in
let uinfo = { uinfo with primitives = uinfo.primitives @ prims } in
let code : Parse_bytecode.one =
{ code
Expand Down Expand Up @@ -322,7 +323,6 @@ let run
let linkall = linkall || toplevel || dynlink in
let code =
Parse_bytecode.from_exe
~target:`JavaScript
~includes:include_dirs
~include_cmis
~link_info:(toplevel || dynlink)
Expand Down Expand Up @@ -355,7 +355,6 @@ let run
let t1 = Timer.make () in
let code =
Parse_bytecode.from_cmo
~target:`JavaScript
~includes:include_dirs
~include_cmis
~debug:need_debug
Expand Down Expand Up @@ -412,7 +411,6 @@ let run
let t1 = Timer.make () in
let code =
Parse_bytecode.from_cmo
~target:`JavaScript
~includes:include_dirs
~include_cmis
~debug:need_debug
Expand Down Expand Up @@ -444,7 +442,6 @@ let run
let t1 = Timer.make () in
let code =
Parse_bytecode.from_cmo
~target:`JavaScript
~includes:include_dirs
~include_cmis
~debug:need_debug
Expand Down
1 change: 1 addition & 0 deletions compiler/bin-js_of_ocaml/link.ml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ let f
; mklib
; toplevel
} =
Config.set_target `JavaScript;
Jsoo_cmdline.Arg.eval common;
let with_output f =
match output_file with
Expand Down
57 changes: 28 additions & 29 deletions compiler/bin-wasm_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ let update_sourcemap ~sourcemap_root ~sourcemap_don't_inline_content sourcemap_f
if Option.is_some sourcemap_root || not sourcemap_don't_inline_content
then (
let open Source_map in
let source_map, mappings = Source_map.of_file_no_mappings sourcemap_file in
let source_map = Source_map.of_file sourcemap_file in
assert (List.is_empty (Option.value source_map.sources_content ~default:[]));
(* Add source file contents to source map *)
let sources_content =
Expand All @@ -50,7 +50,7 @@ let update_sourcemap ~sourcemap_root ~sourcemap_don't_inline_content sourcemap_f
(if Option.is_some sourcemap_root then sourcemap_root else source_map.sourceroot)
}
in
Source_map.to_file ?mappings source_map ~file:sourcemap_file)
Source_map.to_file source_map sourcemap_file)

let opt_with action x f =
match x with
Expand Down Expand Up @@ -140,17 +140,23 @@ let link_runtime ~profile runtime_wasm_files output_file =
let generate_prelude ~out_file =
Filename.gen_file out_file
@@ fun ch ->
let code, uinfo = Parse_bytecode.predefined_exceptions ~target:`Wasm in
let live_vars, in_cps, p, debug =
Driver.f
~target:Wasm
~link:`Needed
(Parse_bytecode.Debug.create ~include_cmis:false false)
code
let code, uinfo = Parse_bytecode.predefined_exceptions () in
let profile =
match Driver.profile 1 with
| Some p -> p
| None -> assert false
in
let Driver.{ program; variable_uses; in_cps; _ } = Driver.optimize ~profile code in
let context = Wa_generate.start () in
let debug = Parse_bytecode.Debug.create ~include_cmis:false false in
let _ =
Wa_generate.f ~context ~unit_name:(Some "prelude") ~live_vars ~in_cps ~debug p
Wa_generate.f
~context
~unit_name:(Some "prelude")
~live_vars:variable_uses
~in_cps
~debug
program
in
Wa_generate.output ch ~context ~debug;
uinfo.provides
Expand Down Expand Up @@ -244,6 +250,7 @@ let run
; sourcemap_root
; sourcemap_don't_inline_content
} =
Config.set_target `Wasm;
Jsoo_cmdline.Arg.eval common;
Wa_generate.init ();
let output_file = fst output_file in
Expand All @@ -270,15 +277,8 @@ let run
List.iter builtin ~f:(fun t ->
let filename = Builtins.File.name t in
let runtimes = Linker.Fragment.parse_builtin t in
Linker.load_fragments
~ignore_always_annotation:true
~target_env:Target_env.Isomorphic
~filename
runtimes);
Linker.load_files
~ignore_always_annotation:true
~target_env:Target_env.Isomorphic
runtime_js_files;
Linker.load_fragments ~target_env:Target_env.Isomorphic ~filename runtimes);
Linker.load_files ~target_env:Target_env.Isomorphic runtime_js_files;
Linker.check_deps ();
if times () then Format.eprintf " parsing js: %a@." Timer.print t1;
if times () then Format.eprintf "Start parsing...@.";
Expand All @@ -299,12 +299,17 @@ let run
check_debug one;
let code = one.code in
let standalone = Option.is_none unit_name in
let live_vars, in_cps, p, debug =
Driver.f ~target:Wasm ~standalone ?profile ~link:`No one.debug code
let profile =
match profile, Driver.profile 1 with
| Some p, _ -> p
| None, Some p -> p
| None, None -> assert false
in
let Driver.{ program; variable_uses; in_cps; _ } = Driver.optimize ~profile code in
let context = Wa_generate.start () in
let debug = one.debug in
let toplevel_name, generated_js =
Wa_generate.f ~context ~unit_name ~live_vars ~in_cps ~debug p
Wa_generate.f ~context ~unit_name ~live_vars:variable_uses ~in_cps ~debug program
in
if standalone then Wa_generate.add_start_function ~context toplevel_name;
Wa_generate.output ch ~context ~debug;
Expand Down Expand Up @@ -352,12 +357,7 @@ let run
let compile_cmo cmo cont =
let t1 = Timer.make () in
let code =
Parse_bytecode.from_cmo
~target:`Wasm
~includes:include_dirs
~debug:need_debug
cmo
ic
Parse_bytecode.from_cmo ~includes:include_dirs ~debug:need_debug cmo ic
in
let unit_info = Unit_info.of_cmo cmo in
let unit_name = Ocaml_compiler.Cmo_format.name cmo in
Expand Down Expand Up @@ -391,7 +391,6 @@ let run
let t1 = Timer.make () in
let code =
Parse_bytecode.from_exe
~target:`Wasm
~includes:include_dirs
~include_cmis:false
~link_info:false
Expand Down
3 changes: 3 additions & 0 deletions compiler/lib-dynlink/js_of_ocaml_compiler_dynlink.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ let split_primitives p =
external get_section_table : unit -> (string * Obj.t) list = "caml_get_section_table"

let () =
(match Sys.backend_type with
| Sys.Other "js_of_ocaml" -> Config.set_target `JavaScript
| Sys.(Native | Bytecode | Other _) -> failwith "Expected backend `js_of_ocaml`");
let global = J.pure_js_expr "globalThis" in
Config.Flag.set "use-js-string" (Jsoo_runtime.Sys.Config.use_js_string ());
Config.Flag.set "effects" (Jsoo_runtime.Sys.Config.effects ());
Expand Down
1 change: 1 addition & 0 deletions compiler/lib-runtime-files/gen/gen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ let rec list_product l =
let bool = [ true; false ]

let () =
Js_of_ocaml_compiler.Config.set_target `JavaScript;
let () = set_binary_mode_out stdout true in
match Array.to_list Sys.argv with
| [] -> assert false
Expand Down
30 changes: 22 additions & 8 deletions compiler/lib/code.ml
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,10 @@ type constant =
| NativeString of Native_string.t
| Float of float
| Float_array of float array
| Int of int32
| Int32 of int32
| Int64 of int64
| NativeInt of nativeint
| Int of Int32.t
| Int32 of Int32.t
| Int64 of Int64.t
| NativeInt of Int32.t (* Native int are 32bit on all known backend *)
| Tuple of int * constant array * array_or_not

module Constant = struct
Expand All @@ -311,7 +311,7 @@ module Constant = struct
!same
| Int a, Int b | Int32 a, Int32 b -> Some (Int32.equal a b)
| Int64 a, Int64 b -> Some (Int64.equal a b)
| NativeInt a, NativeInt b -> Some (Nativeint.equal a b)
| NativeInt a, NativeInt b -> Some (Int32.equal a b)
| Float_array a, Float_array b -> Some (Array.equal Float.ieee_equal a b)
| Float a, Float b -> Some (Float.ieee_equal a b)
| String _, NativeString _ | NativeString _, String _ -> None
Expand Down Expand Up @@ -459,7 +459,7 @@ module Print = struct
| Int i -> Format.fprintf f "%ld" i
| Int32 i -> Format.fprintf f "%ldl" i
| Int64 i -> Format.fprintf f "%LdL" i
| NativeInt i -> Format.fprintf f "%ndn" i
| NativeInt i -> Format.fprintf f "%ldn" i
| Tuple (tag, a, _) -> (
Format.fprintf f "<%d>" tag;
match Array.length a with
Expand Down Expand Up @@ -816,6 +816,7 @@ let with_invariant = Debug.find "invariant"
let check_defs = false

let invariant { blocks; start; _ } =
let target = Config.target () in
if with_invariant ()
then (
assert (Addr.Map.mem start blocks);
Expand All @@ -830,15 +831,28 @@ let invariant { blocks; start; _ } =
assert (not (Var.ISet.mem defs x));
Var.ISet.add defs x)
in
let check_constant = function
| NativeInt _ | Int32 _ ->
assert (
match target with
| `Wasm -> true
| _ -> false)
| String _ | NativeString _ | Float _ | Float_array _ | Int _ | Int64 _
| Tuple (_, _, _) -> ()
in
let check_prim_arg = function
| Pc c -> check_constant c
| Pv _ -> ()
in
let check_expr = function
| Apply _ -> ()
| Block (_, _, _, _) -> ()
| Field (_, _, _) -> ()
| Closure (l, cont) ->
List.iter l ~f:define;
check_cont cont
| Constant _ -> ()
| Prim (_, _) -> ()
| Constant c -> check_constant c
| Prim (_, args) -> List.iter ~f:check_prim_arg args
| Special _ -> ()
in
let check_instr (i, _loc) =
Expand Down
8 changes: 4 additions & 4 deletions compiler/lib/code.mli
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ type constant =
| NativeString of Native_string.t
| Float of float
| Float_array of float array
| Int of int32
| Int32 of int32 (** Only produced when compiling to WebAssembly. *)
| Int64 of int64
| NativeInt of nativeint (** Only produced when compiling to WebAssembly. *)
| Int of Int32.t
| Int32 of Int32.t (** Only produced when compiling to WebAssembly. *)
| Int64 of Int64.t
| NativeInt of Int32.t (** Only produced when compiling to WebAssembly. *)
| Tuple of int * constant array * array_or_not

module Constant : sig
Expand Down
14 changes: 13 additions & 1 deletion compiler/lib/config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ module Param = struct
p
~name:"tc"
~desc:"Set tailcall optimisation"
(enum [ "trampoline", TcTrampoline; (* default *) "none", TcNone ])
(enum [ "trampoline", TcTrampoline (* default *); "none", TcNone ])

let lambda_lifting_threshold =
(* When we reach this depth, we start looking for functions to be lifted *)
Expand All @@ -178,3 +178,15 @@ module Param = struct
~desc:"Set baseline for lifting deeply nested functions"
(int 1)
end

(****)

let target_ : [ `JavaScript | `Wasm | `None ] ref = ref `None

let target () =
match !target_ with
| `None -> failwith "target was not set"
| (`JavaScript | `Wasm) as t -> t

let set_target (t : [ `JavaScript | `Wasm ]) =
target_ := (t :> [ `JavaScript | `Wasm | `None ])
11 changes: 11 additions & 0 deletions compiler/lib/config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ module Flag : sig
val disable : string -> unit
end

(** This module contains parameters that may be modified through command-line flags. *)
module Param : sig
val set : string -> string -> unit

Expand All @@ -102,3 +103,13 @@ module Param : sig

val lambda_lifting_baseline : unit -> int
end

(****)

(** {2 Parameters that are constant across a program run} *)

(** These parameters should be set at most once at the beginning of the program. *)

val target : unit -> [ `JavaScript | `Wasm ]

val set_target : [ `JavaScript | `Wasm ] -> unit
Loading