Skip to content

Commit 46cf942

Browse files
committed
Compiler: move primitive generation in the runtime
1 parent 713bfba commit 46cf942

26 files changed

+512
-248
lines changed

compiler/bin-js_of_ocaml/check_runtime.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ let f (runtime_files, bytecode, target_env) =
4646
Config.set_target `JavaScript;
4747
Config.set_effects_backend `Disabled;
4848
Linker.reset ();
49+
Generate.reset ();
4950
let runtime_files, builtin =
5051
List.partition_map runtime_files ~f:(fun name ->
5152
match Builtins.find name with

compiler/bin-js_of_ocaml/compile.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ let run
166166
Jsoo_cmdline.Arg.eval common;
167167
Config.set_effects_backend effects;
168168
Linker.reset ();
169+
Generate.reset ();
169170
(match output_file with
170171
| `Stdout, _ -> ()
171172
| `Name name, _ when debug_mem () -> Debug.start_profiling name

compiler/bin-js_of_ocaml/link.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ let f
162162
Config.set_target `JavaScript;
163163
Jsoo_cmdline.Arg.eval common;
164164
Linker.reset ();
165+
Generate.reset ();
165166
let with_output f =
166167
match output_file with
167168
| None -> f stdout

compiler/lib-dynlink/js_of_ocaml_compiler_dynlink.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ let () =
4545
Config.set_effects_backend (Jsoo_runtime.Sys.Config.effects ());
4646
Linker.reset ();
4747
List.iter aliases ~f:(fun (a, b) -> Primitive.alias a b);
48+
Generate.reset ();
4849
(* this needs to stay synchronized with toplevel.js *)
4950
let toplevel_compile (s : string) (debug : Instruct.debug_event list array) :
5051
unit -> J.t =

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ let () =
7373
| `Effects b -> Js_of_ocaml_compiler.Config.set_effects_backend b);
7474
List.iter Js_of_ocaml_compiler.Target_env.all ~f:(fun target_env ->
7575
Js_of_ocaml_compiler.Linker.reset ();
76+
Js_of_ocaml_compiler.Generate.reset ();
7677
List.iter fragments ~f:(fun (filename, frags) ->
7778
Js_of_ocaml_compiler.Linker.load_fragments ~target_env ~filename frags);
7879
let linkinfos = Js_of_ocaml_compiler.Linker.init () in

compiler/lib/annot_lexer.mll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ rule main = parse
2525
| "Requires" {TRequires}
2626
| "Version" {TVersion}
2727
| "Weakdef" {TWeakdef}
28+
| "Inline" {TInline}
2829
| "Always" {TAlways}
2930
| "If" {TIf}
3031
| "Alias" {TAlias}

compiler/lib/annot_parser.mly

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1818
*)
1919

20-
%token TProvides TRequires TVersion TWeakdef TIf TAlways TAlias
20+
%token TProvides TRequires TVersion TWeakdef TInline TIf TAlways TAlias
2121
%token TA_Pure TA_Const TA_Mutable TA_Mutator TA_Shallow TA_Object_literal
2222
%token<string> TIdent TIdent_percent TVNum
2323
%token TComma TColon EOF EOL LE LT GE GT EQ LPARENT RPARENT
@@ -40,6 +40,7 @@ annot:
4040
| TVersion TColon l=separated_nonempty_list(TComma,version) endline
4141
{ `Version (l) }
4242
| TWeakdef endline { `Weakdef }
43+
| TInline endline { `Inline }
4344
| TAlways endline { `Always }
4445
| TDeprecated endline { `Deprecated $1 }
4546
| TAlias TColon name=TIdent endline { `Alias (name) }

compiler/lib/generate.ml

Lines changed: 56 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,6 @@ let one = J.ENum (J.Num.of_targetint Targetint.one)
365365

366366
let zero = J.ENum (J.Num.of_targetint Targetint.zero)
367367

368-
let plus_int x y =
369-
match x, y with
370-
| J.ENum y, x when J.Num.is_zero y -> x
371-
| x, J.ENum y when J.Num.is_zero y -> x
372-
| J.ENum x, J.ENum y -> J.ENum (J.Num.add x y)
373-
| x, y -> J.EBin (J.Plus, x, y)
374-
375368
let bool e = J.ECond (e, one, zero)
376369

377370
(****)
@@ -1082,16 +1075,6 @@ let register_un_prims names ?(need_loc = false) k f =
10821075

10831076
let register_un_prim name k f = register_un_prims [ name ] k f
10841077

1085-
let register_un_prim_ctx name k f =
1086-
register_prims [ name ] k (fun name l ctx loc ->
1087-
match l with
1088-
| [ x ] ->
1089-
let open Expr_builder in
1090-
let* cx = access' ~ctx x in
1091-
let* () = info (kind k) in
1092-
return (f ctx cx loc)
1093-
| _ -> invalid_arity name l ~loc ~expected:1)
1094-
10951078
let register_bin_prims names k f =
10961079
register_prims names k (fun name l ctx loc ->
10971080
match l with
@@ -1119,28 +1102,7 @@ let register_tern_prims names k f =
11191102

11201103
let register_tern_prim name k f = register_tern_prims [ name ] k f
11211104

1122-
let register_un_math_prim name prim =
1123-
let prim = Utf8_string.of_string_exn prim in
1124-
register_un_prim name `Pure (fun cx loc ->
1125-
J.call (J.dot (s_var "Math") prim) [ cx ] loc)
1126-
1127-
let register_bin_math_prim name prim =
1128-
let prim = Utf8_string.of_string_exn prim in
1129-
register_bin_prims [ name ] `Pure (fun cx cy loc ->
1130-
J.call (J.dot (s_var "Math") prim) [ cx; cy ] loc)
1131-
11321105
let _ =
1133-
register_un_prim_ctx "%caml_format_int_special" `Pure (fun ctx cx loc ->
1134-
let s = J.EBin (J.Plus, str_js_utf8 "", cx) in
1135-
ocaml_string ~ctx ~loc s);
1136-
register_un_prim "%direct_obj_tag" `Pure (fun cx _loc -> Mlvalue.Block.tag cx);
1137-
register_bin_prims
1138-
[ "caml_array_unsafe_get"
1139-
; "caml_array_unsafe_get_float"
1140-
; "caml_floatarray_unsafe_get"
1141-
]
1142-
`Mutable
1143-
(fun cx cy _ -> Mlvalue.Array.field cx cy);
11441106
register_un_prims
11451107
[ "caml_int32_of_int"
11461108
; "caml_int32_to_int"
@@ -1154,83 +1116,6 @@ let _ =
11541116
]
11551117
`Pure
11561118
(fun cx _ -> cx);
1157-
register_bin_prims
1158-
[ "%int_add"; "caml_int32_add"; "caml_nativeint_add" ]
1159-
`Pure
1160-
(fun cx cy _ ->
1161-
match cx, cy with
1162-
| J.EBin (J.Minus, cz, J.ENum n), J.ENum m ->
1163-
to_int (J.EBin (J.Plus, cz, J.ENum (J.Num.add m (J.Num.neg n))))
1164-
| _ -> to_int (plus_int cx cy));
1165-
register_bin_prims
1166-
[ "%int_sub"; "caml_int32_sub"; "caml_nativeint_sub" ]
1167-
`Pure
1168-
(fun cx cy _ ->
1169-
match cx, cy with
1170-
| J.EBin (J.Minus, cz, J.ENum n), J.ENum m ->
1171-
to_int (J.EBin (J.Minus, cz, J.ENum (J.Num.add n m)))
1172-
| _ -> to_int (J.EBin (J.Minus, cx, cy)));
1173-
register_bin_prim "%direct_int_mul" `Pure (fun cx cy _ ->
1174-
to_int (J.EBin (J.Mul, cx, cy)));
1175-
register_bin_prim "%direct_int_div" `Pure (fun cx cy _ ->
1176-
to_int (J.EBin (J.Div, cx, cy)));
1177-
register_bin_prim "%direct_int_mod" `Pure (fun cx cy _ ->
1178-
to_int (J.EBin (J.Mod, cx, cy)));
1179-
register_bin_prims
1180-
[ "%int_and"; "caml_int32_and"; "caml_nativeint_and" ]
1181-
`Pure
1182-
(fun cx cy _ -> J.EBin (J.Band, cx, cy));
1183-
register_bin_prims
1184-
[ "%int_or"; "caml_int32_or"; "caml_nativeint_or" ]
1185-
`Pure
1186-
(fun cx cy _ -> J.EBin (J.Bor, cx, cy));
1187-
register_bin_prims
1188-
[ "%int_xor"; "caml_int32_xor"; "caml_nativeint_xor" ]
1189-
`Pure
1190-
(fun cx cy _ -> J.EBin (J.Bxor, cx, cy));
1191-
register_bin_prims
1192-
[ "%int_lsl"; "caml_int32_shift_left"; "caml_nativeint_shift_left" ]
1193-
`Pure
1194-
(fun cx cy _ -> J.EBin (J.Lsl, cx, cy));
1195-
register_bin_prims
1196-
[ "%int_lsr"
1197-
; "caml_int32_shift_right_unsigned"
1198-
; "caml_nativeint_shift_right_unsigned"
1199-
]
1200-
`Pure
1201-
(fun cx cy _ -> to_int (J.EBin (J.Lsr, cx, cy)));
1202-
register_bin_prims
1203-
[ "%int_asr"; "caml_int32_shift_right"; "caml_nativeint_shift_right" ]
1204-
`Pure
1205-
(fun cx cy _ -> J.EBin (J.Asr, cx, cy));
1206-
register_un_prims
1207-
[ "%int_neg"; "caml_int32_neg"; "caml_nativeint_neg" ]
1208-
`Pure
1209-
(fun cx _ -> to_int (J.EUn (J.Neg, cx)));
1210-
register_bin_prim "caml_eq_float" `Pure (fun cx cy _ ->
1211-
bool (J.EBin (J.EqEqEq, cx, cy)));
1212-
register_bin_prim "caml_neq_float" `Pure (fun cx cy _ ->
1213-
bool (J.EBin (J.NotEqEq, cx, cy)));
1214-
register_bin_prim "caml_ge_float" `Pure (fun cx cy _ -> bool (J.EBin (J.Le, cy, cx)));
1215-
register_bin_prim "caml_le_float" `Pure (fun cx cy _ -> bool (J.EBin (J.Le, cx, cy)));
1216-
register_bin_prim "caml_gt_float" `Pure (fun cx cy _ -> bool (J.EBin (J.Lt, cy, cx)));
1217-
register_bin_prim "caml_lt_float" `Pure (fun cx cy _ -> bool (J.EBin (J.Lt, cx, cy)));
1218-
register_bin_prim "caml_add_float" `Pure (fun cx cy _ -> J.EBin (J.Plus, cx, cy));
1219-
register_bin_prim "caml_sub_float" `Pure (fun cx cy _ -> J.EBin (J.Minus, cx, cy));
1220-
register_bin_prim "caml_mul_float" `Pure (fun cx cy _ -> J.EBin (J.Mul, cx, cy));
1221-
register_bin_prim "caml_div_float" `Pure (fun cx cy _ -> J.EBin (J.Div, cx, cy));
1222-
register_un_prim "caml_neg_float" `Pure (fun cx _ -> J.EUn (J.Neg, cx));
1223-
register_bin_prim "caml_fmod_float" `Pure (fun cx cy _ -> J.EBin (J.Mod, cx, cy));
1224-
register_tern_prims
1225-
[ "caml_array_unsafe_set"
1226-
; "caml_array_unsafe_set_float"
1227-
; "caml_floatarray_unsafe_set"
1228-
; "caml_array_unsafe_set_addr"
1229-
]
1230-
`Mutator
1231-
(fun cx cy cz _ -> J.EBin (J.Eq, Mlvalue.Array.field cx cy, cz));
1232-
register_un_prims [ "caml_alloc_dummy"; "caml_alloc_dummy_float" ] `Pure (fun _ _ ->
1233-
J.array []);
12341119
register_un_prims
12351120
[ "caml_int_of_float"
12361121
; "caml_int32_of_float"
@@ -1240,20 +1125,6 @@ let _ =
12401125
]
12411126
`Pure
12421127
(fun cx _loc -> to_int cx);
1243-
register_un_math_prim "caml_abs_float" "abs";
1244-
register_un_math_prim "caml_acos_float" "acos";
1245-
register_un_math_prim "caml_asin_float" "asin";
1246-
register_un_math_prim "caml_atan_float" "atan";
1247-
register_bin_math_prim "caml_atan2_float" "atan2";
1248-
register_un_math_prim "caml_ceil_float" "ceil";
1249-
register_un_math_prim "caml_cos_float" "cos";
1250-
register_un_math_prim "caml_exp_float" "exp";
1251-
register_un_math_prim "caml_floor_float" "floor";
1252-
register_un_math_prim "caml_log_float" "log";
1253-
register_bin_math_prim "caml_power_float" "pow";
1254-
register_un_math_prim "caml_sin_float" "sin";
1255-
register_un_math_prim "caml_sqrt_float" "sqrt";
1256-
register_un_math_prim "caml_tan_float" "tan";
12571128
register_un_prim "caml_js_from_bool" `Pure (fun cx _ ->
12581129
J.EUn (J.Not, J.EUn (J.Not, cx)));
12591130
register_un_prim "caml_js_to_bool" `Pure (fun cx _ -> to_int cx);
@@ -1318,6 +1189,17 @@ let remove_unused_tail_args ctx exact trampolined args =
13181189
else args
13191190
else args
13201191

1192+
(* var substitution *)
1193+
class subst sub =
1194+
object
1195+
inherit Js_traverse.map as super
1196+
1197+
method expression x =
1198+
match x with
1199+
| EVar v -> ( try sub v with Not_found -> super#expression x)
1200+
| _ -> super#expression x
1201+
end
1202+
13211203
let rec translate_expr ctx loc x e level : (_ * J.statement_list) Expr_builder.t =
13221204
let open Expr_builder in
13231205
match e with
@@ -1539,13 +1421,52 @@ let rec translate_expr ctx loc x e level : (_ * J.statement_list) Expr_builder.t
15391421
let name = Primitive.resolve name_orig in
15401422
match internal_prim name with
15411423
| Some f -> f name l ctx loc
1542-
| None ->
1424+
| None -> (
15431425
if String.starts_with name ~prefix:"%"
15441426
then failwith (Printf.sprintf "Unresolved internal primitive: %s" name);
1545-
let prim = Share.get_prim (runtime_fun ctx) name ctx.Ctx.share in
1546-
let* () = info ~need_loc:true (kind (Primitive.kind name)) in
1547-
let* args = list_map (fun x -> access' ~ctx x) l in
1548-
return (J.call prim args loc))
1427+
match Linker.inline ~name with
1428+
| Some (req, f)
1429+
when Option.is_none ctx.Ctx.exported_runtime || List.is_empty req -> (
1430+
let c = new Js_traverse.rename_variable ~esm:false in
1431+
let f = c#expression f in
1432+
match f with
1433+
| EFun
1434+
( None
1435+
, ( { async = false; generator = false }
1436+
, { list = params; rest = None }
1437+
, [ (Return_statement (Some body, _), _) ]
1438+
, _loc ) )
1439+
when List.length params = List.length l ->
1440+
let* l = list_map (fun x -> access' ~ctx x) l in
1441+
let params =
1442+
List.map params ~f:(fun (x, _) ->
1443+
match x with
1444+
| BindingIdent x -> x
1445+
| BindingPattern _ -> assert false)
1446+
in
1447+
let sub =
1448+
let t = Hashtbl.create (List.length l) in
1449+
List.iter2 params l ~f:(fun p x ->
1450+
let k =
1451+
match p with
1452+
| J.V v -> v
1453+
| _ -> assert false
1454+
in
1455+
Hashtbl.add t k x);
1456+
1457+
fun x ->
1458+
match x with
1459+
| J.S _ -> J.EVar x
1460+
| J.V x -> Hashtbl.find t x
1461+
in
1462+
let r = new subst sub in
1463+
return (r#expression body)
1464+
| _ -> assert false)
1465+
| None | Some _ ->
1466+
let prim = Share.get_prim (runtime_fun ctx) name ctx.Ctx.share in
1467+
let* () = info ~need_loc:true (kind (Primitive.kind name)) in
1468+
let* args = list_map (fun x -> access' ~ctx x) l in
1469+
return (J.call prim args loc)))
15491470
| Not, [ x ] ->
15501471
let* cx = access' ~ctx x in
15511472
return (J.EBin (J.Minus, one, cx))
@@ -2289,7 +2210,7 @@ let f
22892210
if times () then Format.eprintf " code gen.: %a@." Timer.print t';
22902211
p
22912212

2292-
let init () =
2213+
let reset () =
22932214
Hashtbl.iter
22942215
(fun name (k, _) -> Primitive.register name k None None)
22952216
internal_primitives

compiler/lib/generate.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ val f :
2929
-> deadcode_sentinal:Code.Var.t
3030
-> Javascript.program
3131

32-
val init : unit -> unit
32+
val reset : unit -> unit

compiler/lib/javascript.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ module Num : sig
4242

4343
val is_neg : t -> bool
4444

45+
val is_int : t -> bool
46+
4547
(** Arithmetic *)
4648

4749
val add : t -> t -> t
@@ -134,6 +136,11 @@ end = struct
134136

135137
let is_neg s = Char.equal s.[0] '-'
136138

139+
let is_int s =
140+
String.for_all s ~f:(function
141+
| '0' .. '9' | '-' -> true
142+
| _ -> false)
143+
137144
let neg s =
138145
match String.drop_prefix s ~prefix:"-" with
139146
| None -> "-" ^ s

compiler/lib/javascript.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ module Num : sig
4343

4444
val is_neg : t -> bool
4545

46+
val is_int : t -> bool
47+
4648
(** Arithmetic *)
4749

4850
val add : t -> t -> t

compiler/lib/js_traverse.ml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,23 +1702,23 @@ class simpl =
17021702

17031703
method expression e =
17041704
let e = super#expression e in
1705-
let is_zero x =
1706-
match Num.to_string x with
1707-
| "0" | "0." -> true
1708-
| _ -> false
1709-
in
17101705
match e with
17111706
| EBin (Plus, e1, e2) -> (
17121707
match e1, e2 with
1713-
| _, ENum n when Num.is_neg n -> EBin (Minus, e1, ENum (Num.neg n))
1714-
| ENum n, _ when Num.is_neg n -> EBin (Minus, e2, ENum (Num.neg n))
1715-
| ENum zero, (ENum _ as x) when is_zero zero -> x
1716-
| (ENum _ as x), ENum zero when is_zero zero -> x
1708+
| ENum n1, ENum n2 when Num.is_int n1 && Num.is_int n2 -> ENum (Num.add n1 n2)
1709+
| _, ENum n when Num.is_neg n ->
1710+
m#expression (EBin (Minus, e1, ENum (Num.neg n)))
1711+
| ENum n, _ when Num.is_neg n ->
1712+
m#expression (EBin (Minus, e2, ENum (Num.neg n)))
1713+
| ENum zero, x when Num.is_zero zero -> x
1714+
| x, ENum zero when Num.is_zero zero -> x
17171715
| _ -> e)
17181716
| EBin (Minus, e1, e2) -> (
17191717
match e1, e2 with
1718+
| EBin (Minus, e0, ENum n1), ENum n2 when Num.is_int n1 && Num.is_int n2 ->
1719+
EBin (Minus, e0, ENum (Num.add n1 n2))
17201720
| _, ENum n when Num.is_neg n -> EBin (Plus, e1, ENum (Num.neg n))
1721-
| (ENum _ as x), ENum zero when is_zero zero -> x
1721+
| (ENum _ as x), ENum zero when Num.is_zero zero -> x
17221722
| _ -> e)
17231723
| EFun
17241724
(None, (({ generator = false; async = true | false }, _, body, _) as fun_decl))

0 commit comments

Comments
 (0)