diff --git a/compiler/lib/code.ml b/compiler/lib/code.ml index cb3bf0e922..ee704a6a5c 100644 --- a/compiler/lib/code.ml +++ b/compiler/lib/code.ml @@ -327,7 +327,7 @@ type constant = | NativeString of Native_string.t | Float of float | Float_array of float array - | Int of Int32.t + | Int of Targetint.t | Int32 of Int32.t | Int64 of Int64.t | NativeInt of Int32.t (* Native int are 32bit on all known backend *) @@ -352,7 +352,8 @@ module Constant = struct | Some s, Some c -> same := Some (s && c) done; !same - | Int a, Int b | Int32 a, Int32 b -> Some (Int32.equal a b) + | Int a, Int b -> Some (Targetint.equal a b) + | Int32 a, Int32 b -> Some (Int32.equal a b) | Int64 a, Int64 b -> Some (Int64.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) @@ -497,7 +498,7 @@ module Print = struct Format.fprintf f "%.12g" a.(i) done; Format.fprintf f "|]" - | Int i -> Format.fprintf f "%ld" i + | Int i -> Format.fprintf f "%s" (Targetint.to_string i) | Int32 i -> Format.fprintf f "%ldl" i | Int64 i -> Format.fprintf f "%LdL" i | NativeInt i -> Format.fprintf f "%ldn" i diff --git a/compiler/lib/code.mli b/compiler/lib/code.mli index 639b470312..699aa220fb 100644 --- a/compiler/lib/code.mli +++ b/compiler/lib/code.mli @@ -173,7 +173,7 @@ type constant = | NativeString of Native_string.t | Float of float | Float_array of float array - | Int of Int32.t + | Int of Targetint.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. *) diff --git a/compiler/lib/config.ml b/compiler/lib/config.ml index d38b798f69..29f39a1f02 100644 --- a/compiler/lib/config.ml +++ b/compiler/lib/config.ml @@ -191,4 +191,7 @@ let target () = | (`JavaScript | `Wasm) as t -> t let set_target (t : [ `JavaScript | `Wasm ]) = + (match t with + | `JavaScript -> Targetint.set_num_bits 32 + | `Wasm -> Targetint.set_num_bits 31); target_ := (t :> [ `JavaScript | `Wasm | `None ]) diff --git a/compiler/lib/effects.ml b/compiler/lib/effects.ml index 05e3ae3c2a..5cbaf29ac9 100644 --- a/compiler/lib/effects.ml +++ b/compiler/lib/effects.ml @@ -300,7 +300,7 @@ let cps_branch ~st ~src (pc, args) loc = (* We are jumping to a block that is also used as a continuation. We pass it a dummy argument. *) let x = Var.fresh () in - [ x ], [ Let (x, Constant (Int 0l)), noloc ] + [ x ], [ Let (x, Constant (Int Targetint.zero)), noloc ] else args, [] in (* We check the stack depth only for backward edges (so, at @@ -402,7 +402,9 @@ let cps_last ~st ~alloc_jump_closures pc ((last, last_loc) : last * loc) ~k : ( x' , Prim ( Extern "caml_maybe_attach_backtrace" - , [ Pv x; Pc (Int (if force then 1l else 0l)) ] ) ) + , [ Pv x + ; Pc (Int (if force then Targetint.one else Targetint.zero)) + ] ) ) , noloc ) ] in @@ -483,7 +485,8 @@ let cps_instr ~st (instr : instr) : instr = | Pc (Int a) -> Let ( x - , Prim (Extern "caml_alloc_dummy_function", [ size; Pc (Int (Int32.succ a)) ]) + , Prim + (Extern "caml_alloc_dummy_function", [ size; Pc (Int (Targetint.succ a)) ]) ) | _ -> assert false) | Let (x, Apply { f; args; _ }) when not (Var.Set.mem x st.cps_needed) -> @@ -562,7 +565,7 @@ let cps_block ~st ~k pc block = [ arg; k' ] loc) | Prim (Extern "%perform", [ Pv effect_ ]) -> - perform_effect ~effect_ ~continuation:(Pc (Int 0l)) loc + perform_effect ~effect_ ~continuation:(Pc (Int Targetint.zero)) loc | Prim (Extern "%reperform", [ Pv effect_; continuation ]) -> perform_effect ~effect_ ~continuation loc | _ -> None diff --git a/compiler/lib/eval.ml b/compiler/lib/eval.ml index 433d4d656b..113fe6432b 100644 --- a/compiler/lib/eval.ml +++ b/compiler/lib/eval.ml @@ -29,81 +29,29 @@ let set_static_env s value = Hashtbl.add static_env s value let get_static_env s = try Some (Hashtbl.find static_env s) with Not_found -> None -module type Int = sig - include Arith_ops - - val int_unop : constant list -> (t -> t) -> constant option - - val int_binop : constant list -> (t -> t -> t) -> constant option - - val shift_op : constant list -> (t -> int -> t) -> constant option - - val of_int32_warning_on_overflow : int32 -> t - - val to_int32 : t -> int32 - - val numbits : int -end - -module Int32 = struct - include Int32 - - let int_unop l f = - match l with - | [ Int i ] -> Some (Int (f i)) - | _ -> None - - let int_binop l f = - match l with - | [ Int i; Int j ] -> Some (Int (f i j)) - | _ -> None - - (* For when the underlying function takes an [int] (not [t]) as its second argument *) - let shift_op l f = - match l with - | [ Int i; Int j ] -> Some (Int (f i (to_int j))) - | _ -> None - - let numbits = 32 - - let of_int32_warning_on_overflow = Fun.id - - let to_int32 = Fun.id -end - -module Int31 : Int = struct - include Int31 - - let int_unop l f = - match l with - | [ Int i ] -> Some (Int (to_int32 (f (of_int32_warning_on_overflow i)))) - | _ -> None - - let int_binop l f = - match l with - | [ Int i; Int j ] -> - Some - (Int - (to_int32 - (f (of_int32_warning_on_overflow i) (of_int32_warning_on_overflow j)))) - | _ -> None +let int_unop l f = + match l with + | [ Int i ] -> Some (Int (f i)) + | _ -> None - let shift_op l f = - match l with - | [ Int i; Int j ] -> - Some (Int (to_int32 (f (of_int32_warning_on_overflow i) (Int32.to_int j)))) - | _ -> None +let int_binop l f = + match l with + | [ Int i; Int j ] -> Some (Int (f i j)) + | _ -> None - let numbits = 31 -end +(* For when the underlying function takes an [int] (not [t]) as its second argument *) +let shift_op l f = + match l with + | [ Int i; Int j ] -> Some (Int (f i (Targetint.to_int_exn j))) + | _ -> None let float_binop_aux (l : constant list) (f : float -> float -> 'a) : 'a option = let args = match l with | [ Float i; Float j ] -> Some (i, j) - | [ Int i; Int j ] -> Some (Int32.to_float i, Int32.to_float j) - | [ Int i; Float j ] -> Some (Int32.to_float i, j) - | [ Float i; Int j ] -> Some (i, Int32.to_float j) + | [ Int i; Int j ] -> Some (Targetint.to_float i, Targetint.to_float j) + | [ Int i; Float j ] -> Some (Targetint.to_float i, j) + | [ Float i; Int j ] -> Some (i, Targetint.to_float j) | _ -> None in match args with @@ -118,10 +66,10 @@ let float_binop (l : constant list) (f : float -> float -> float) : constant opt let float_unop (l : constant list) (f : float -> float) : constant option = match l with | [ Float i ] -> Some (Float (f i)) - | [ Int i ] -> Some (Float (f (Int32.to_float i))) + | [ Int i ] -> Some (Float (f (Targetint.to_float i))) | _ -> None -let bool' b = Int (if b then 1l else 0l) +let bool' b = Int Targetint.(if b then one else zero) let bool b = Some (bool' b) @@ -130,36 +78,31 @@ let float_binop_bool l f = | Some b -> bool b | None -> None -let eval_prim ~target x = +let eval_prim x = match x with - | Not, [ Int i ] -> bool Int32.(i = 0l) - | Lt, [ Int i; Int j ] -> bool Int32.(i < j) - | Le, [ Int i; Int j ] -> bool Int32.(i <= j) - | Eq, [ Int i; Int j ] -> bool Int32.(i = j) - | Neq, [ Int i; Int j ] -> bool Int32.(i <> j) - | Ult, [ Int i; Int j ] -> bool (Int32.(j < 0l) || Int32.(i < j)) + | Not, [ Int i ] -> bool (Targetint.is_zero i) + | Lt, [ Int i; Int j ] -> bool Targetint.(i < j) + | Le, [ Int i; Int j ] -> bool Targetint.(i <= j) + | Eq, [ Int i; Int j ] -> bool Targetint.(i = j) + | Neq, [ Int i; Int j ] -> bool Targetint.(i <> j) + | Ult, [ Int i; Int j ] -> bool (Targetint.(j < zero) || Targetint.(i < j)) | Extern name, l -> ( - let (module Int : Int) = - match target with - | `JavaScript -> (module Int32) - | `Wasm -> (module Int31) - in let name = Primitive.resolve name in match name, l with (* int *) - | "%int_add", _ -> Int.int_binop l Int.add - | "%int_sub", _ -> Int.int_binop l Int.sub - | "%direct_int_mul", _ -> Int.int_binop l Int.mul - | "%direct_int_div", [ _; Int 0l ] -> None - | "%direct_int_div", _ -> Int.int_binop l Int.div - | "%direct_int_mod", _ -> Int.int_binop l Int.rem - | "%int_and", _ -> Int.int_binop l Int.logand - | "%int_or", _ -> Int.int_binop l Int.logor - | "%int_xor", _ -> Int.int_binop l Int.logxor - | "%int_lsl", _ -> Int.shift_op l Int.shift_left - | "%int_lsr", _ -> Int.shift_op l Int.shift_right_logical - | "%int_asr", _ -> Int.shift_op l Int.shift_right - | "%int_neg", _ -> Int.int_unop l Int.neg + | "%int_add", _ -> int_binop l Targetint.add + | "%int_sub", _ -> int_binop l Targetint.sub + | "%direct_int_mul", _ -> int_binop l Targetint.mul + | "%direct_int_div", [ _; Int x ] when Targetint.is_zero x -> None + | "%direct_int_div", _ -> int_binop l Targetint.div + | "%direct_int_mod", _ -> int_binop l Targetint.rem + | "%int_and", _ -> int_binop l Targetint.logand + | "%int_or", _ -> int_binop l Targetint.logor + | "%int_xor", _ -> int_binop l Targetint.logxor + | "%int_lsl", _ -> shift_op l Targetint.shift_left + | "%int_lsr", _ -> shift_op l Targetint.shift_right_logical + | "%int_asr", _ -> shift_op l Targetint.shift_right + | "%int_neg", _ -> int_unop l Targetint.neg (* float *) | "caml_eq_float", _ -> float_binop_bool l Float.( = ) | "caml_neq_float", _ -> float_binop_bool l Float.( <> ) @@ -172,9 +115,10 @@ let eval_prim ~target x = | "caml_mul_float", _ -> float_binop l ( *. ) | "caml_div_float", _ -> float_binop l ( /. ) | "caml_fmod_float", _ -> float_binop l mod_float - | "caml_int_of_float", [ Float f ] -> - Some - (Int (Int32.of_float f |> Int.of_int32_warning_on_overflow |> Int.to_int32)) + | "caml_int_of_float", [ Float f ] -> ( + match Targetint.of_float_opt f with + | None -> None + | Some f -> Some (Int f)) (* Math *) | "caml_neg_float", _ -> float_unop l ( ~-. ) | "caml_abs_float", _ -> float_unop l abs_float @@ -192,9 +136,9 @@ let eval_prim ~target x = | "caml_sqrt_float", _ -> float_unop l sqrt | "caml_tan_float", _ -> float_unop l tan | ("caml_string_get" | "caml_string_unsafe_get"), [ String s; Int pos ] -> - let pos = Int32.to_int pos in + let pos = Targetint.to_int_exn pos in if Config.Flag.safe_string () && pos >= 0 && pos < String.length s - then Some (Int (Int32.of_int (Char.code s.[pos]))) + then Some (Int (Targetint.of_int_exn (Char.code s.[pos]))) else None | "caml_string_equal", [ String s1; String s2 ] -> bool (String.equal s1 s2) | "caml_string_notequal", [ String s1; String s2 ] -> @@ -203,10 +147,11 @@ let eval_prim ~target x = match get_static_env s with | Some env -> Some (String env) | None -> None) - | "caml_sys_const_word_size", [ _ ] -> Some (Int 32l) - | "caml_sys_const_int_size", [ _ ] -> Some (Int (Int32.of_int Int.numbits)) - | "caml_sys_const_big_endian", [ _ ] -> Some (Int 0l) - | "caml_sys_const_naked_pointers_checked", [ _ ] -> Some (Int 0l) + | "caml_sys_const_word_size", [ _ ] -> Some (Int (Targetint.of_int_exn 32)) + | "caml_sys_const_int_size", [ _ ] -> + Some (Int (Targetint.of_int_exn (Targetint.num_bits ()))) + | "caml_sys_const_big_endian", [ _ ] -> Some (Int Targetint.zero) + | "caml_sys_const_naked_pointers_checked", [ _ ] -> Some (Int Targetint.zero) | _ -> None) | _ -> None @@ -215,14 +160,14 @@ let the_length_of ~target info x = info (fun x -> match Flow.Info.def info x with - | Some (Constant (String s)) -> Some (Int32.of_int (String.length s)) + | Some (Constant (String s)) -> Some (Targetint.of_int_exn (String.length s)) | Some (Prim (Extern "caml_create_string", [ arg ])) | Some (Prim (Extern "caml_create_bytes", [ arg ])) -> the_int ~target info arg | None | Some _ -> None) None (fun u v -> match u, v with - | Some l, Some l' when Int32.(l = l') -> Some l + | Some l, Some l' when Targetint.(l = l') -> Some l | _ -> None) x @@ -292,7 +237,7 @@ let the_cont_of info x (a : cont array) = (fun x -> match Flow.Info.def info x with | Some (Prim (Extern "%direct_obj_tag", [ b ])) -> the_tag_of info b get - | Some (Constant (Int j)) -> get (Int32.to_int j) + | Some (Constant (Int j)) -> get (Targetint.to_int_exn j) | None | Some _ -> None) None (fun u v -> @@ -304,7 +249,7 @@ let the_cont_of info x (a : cont array) = (* If [constant_js_equal a b = Some v], then [caml_js_equals a b = v]). *) let constant_js_equal a b = match a, b with - | Int i, Int j -> Some (Int32.equal i j) + | Int i, Int j -> Some (Targetint.equal i j) | Float a, Float b -> Some (Float.ieee_equal a b) | NativeString a, NativeString b -> Some (Native_string.equal a b) | String a, String b when Config.Flag.use_js_string () -> Some (String.equal a b) @@ -356,7 +301,7 @@ let eval_instr ~target info ((x, loc) as i) = | Let (x, Prim (Extern "caml_ml_string_length", [ s ])) -> ( let c = match s with - | Pc (String s) -> Some (Int32.of_int (String.length s)) + | Pc (String s) -> Some (Targetint.of_int_exn (String.length s)) | Pv v -> the_length_of ~target info v | _ -> None in @@ -391,7 +336,7 @@ let eval_instr ~target info ((x, loc) as i) = | Let (x, Prim (Extern "%direct_obj_tag", [ y ])) -> ( match the_tag_of info y (fun x -> Some x) with | Some tag -> - let c = Constant (Int (Int32.of_int tag)) in + let c = Constant (Int (Targetint.of_int_exn tag)) in Flow.Info.update_def info x c; [ Let (x, c), loc ] | None -> [ i ]) @@ -415,7 +360,6 @@ let eval_instr ~target info ((x, loc) as i) = | _ -> false) then eval_prim - ~target ( prim , List.map prim_args' ~f:(function | Some c -> c @@ -461,11 +405,10 @@ let the_cond_of info x = info (fun x -> match Flow.Info.def info x with - | Some (Constant (Int 0l)) -> Zero + | Some (Constant (Int x)) -> if Targetint.is_zero x then Zero else Non_zero | Some (Constant - ( Int _ - | Int32 _ + ( Int32 _ | NativeInt _ | Float _ | Tuple _ diff --git a/compiler/lib/flow.ml b/compiler/lib/flow.ml index bf7b079c0c..d93b97389d 100644 --- a/compiler/lib/flow.ml +++ b/compiler/lib/flow.ml @@ -345,7 +345,7 @@ let the_def_of info x = = true]) and if both are floats, they are bitwise equal. *) let constant_identical ~(target : [ `JavaScript | `Wasm ]) a b = match a, b, target with - | Int i, Int j, _ -> Int32.equal i j + | Int i, Int j, _ -> Targetint.equal i j | Float a, Float b, `JavaScript -> Float.bitwise_equal a b | Float _, Float _, `Wasm -> false | NativeString a, NativeString b, `JavaScript -> Native_string.equal a b diff --git a/compiler/lib/flow.mli b/compiler/lib/flow.mli index 1dd89af353..20271a4e3f 100644 --- a/compiler/lib/flow.mli +++ b/compiler/lib/flow.mli @@ -61,6 +61,7 @@ val the_string_of : val the_native_string_of : target:[ `JavaScript | `Wasm ] -> Info.t -> Code.prim_arg -> Code.Native_string.t option -val the_int : target:[ `JavaScript | `Wasm ] -> Info.t -> Code.prim_arg -> int32 option +val the_int : + target:[ `JavaScript | `Wasm ] -> Info.t -> Code.prim_arg -> Targetint.t option val f : ?skip_param:bool -> Code.program -> Code.program * Info.t diff --git a/compiler/lib/generate.ml b/compiler/lib/generate.ml index da6b8947d2..3d1a0a6ee7 100644 --- a/compiler/lib/generate.ml +++ b/compiler/lib/generate.ml @@ -309,9 +309,9 @@ type edge_kind = let var x = J.EVar (J.V x) -let int n = J.ENum (J.Num.of_int32 (Int32.of_int n)) +let int n = J.ENum (J.Num.of_targetint (Targetint.of_int_exn n)) -let int32 n = J.ENum (J.Num.of_int32 n) +let targetint n = J.ENum (J.Num.of_targetint n) let to_int cx = J.EBin (J.Bor, cx, int 0) @@ -325,14 +325,14 @@ let unsigned x = in let pos_int32 = match x with - | J.ENum num -> ( try Int32.(J.Num.to_int32 num >= 0l) with _ -> false) + | J.ENum num -> ( try Targetint.(J.Num.to_targetint num >= zero) with _ -> false) | _ -> false in if pos_int32 then x else unsigned' x -let one = int 1 +let one = J.ENum (J.Num.of_targetint Targetint.one) -let zero = int 0 +let zero = J.ENum (J.Num.of_targetint Targetint.zero) let plus_int x y = match x, y with @@ -455,7 +455,8 @@ let rec constant_rec ~ctx x level instrs = let constant_max_depth = Config.Param.constant_max_depth () in let rec detect_list n acc = function | Tuple (0, [| x; l |], _) -> detect_list (succ n) (x :: acc) l - | Int 0l -> if n > constant_max_depth then Some acc else None + | Int maybe_zero when Targetint.is_zero maybe_zero -> + if n > constant_max_depth then Some acc else None | _ -> None in match detect_list 0 [] x with @@ -492,7 +493,7 @@ let rec constant_rec ~ctx x level instrs = else List.map ~f:(fun x -> J.Element x) (List.rev l), instrs in Mlvalue.Block.make ~tag ~args:l, instrs) - | Int i -> int32 i, instrs + | Int i -> targetint i, instrs | Int32 _ | NativeInt _ -> assert false (* Should not be produced when compiling to Javascript *) @@ -568,9 +569,9 @@ module DTree = struct type cond = | IsTrue - | CEq of int32 - | CLt of int32 - | CLe of int32 + | CEq of Targetint.t + | CLt of Targetint.t + | CLe of Targetint.t type 'a branch = int list * 'a @@ -609,9 +610,9 @@ module DTree = struct (* try to optimize when there are only 2 branch *) match array_norm with | [| (b1, ([ i1 ] as l1)); (b2, l2) |] -> - If (CEq (Int32.of_int i1), Branch (l1, b1), Branch (l2, b2)) + If (CEq (Targetint.of_int_exn i1), Branch (l1, b1), Branch (l2, b2)) | [| (b1, l1); (b2, ([ i2 ] as l2)) |] -> - If (CEq (Int32.of_int i2), Branch (l2, b2), Branch (l1, b1)) + If (CEq (Targetint.of_int_exn i2), Branch (l2, b2), Branch (l1, b1)) | [| (b1, l1); (b2, l2) |] -> let bound l1 = match l1, List.rev l1 with @@ -621,9 +622,9 @@ module DTree = struct let min1, max1 = bound l1 in let min2, max2 = bound l2 in if max1 < min2 - then If (CLt (Int32.of_int max1), Branch (l2, b2), Branch (l1, b1)) + then If (CLt (Targetint.of_int_exn max1), Branch (l2, b2), Branch (l1, b1)) else if max2 < min1 - then If (CLt (Int32.of_int max2), Branch (l1, b1), Branch (l2, b2)) + then If (CLt (Targetint.of_int_exn max2), Branch (l1, b1), Branch (l2, b2)) else raise Not_found | _ -> raise Not_found with Not_found -> ( @@ -641,7 +642,7 @@ module DTree = struct let range1 = snd ai.(h) and range2 = snd ai.(succ h) in match range1, range2 with | [], _ | _, [] -> assert false - | _, lower_bound2 :: _ -> If (CLe (Int32.of_int lower_bound2), b2, b1)) + | _, lower_bound2 :: _ -> If (CLe (Targetint.of_int_exn lower_bound2), b2, b1)) in let len = Array.length ai in assert (len > 0); @@ -1269,7 +1270,7 @@ let rec translate_expr ctx queue loc x e level : _ * J.statement_list = let i, queue = let (_px, cx), queue = access_queue' ~ctx queue size in match cx with - | J.ENum i -> Int32.to_int (J.Num.to_int32 i), queue + | J.ENum i -> Targetint.to_int_exn (J.Num.to_targetint i), queue | _ -> assert false in let args = Array.to_list (Array.init i ~f:(fun _ -> J.V (Var.fresh ()))) in @@ -1668,9 +1669,9 @@ and compile_decision_tree kind st scope_stack loc cx dtree ~fall_through = let e' = match cond with | IsTrue -> cx - | CEq n -> J.EBin (J.EqEqEq, int32 n, cx) - | CLt n -> J.EBin (J.LtInt, int32 n, cx) - | CLe n -> J.EBin (J.LeInt, int32 n, cx) + | CEq n -> J.EBin (J.EqEqEq, targetint n, cx) + | CLt n -> J.EBin (J.LtInt, targetint n, cx) + | CLe n -> J.EBin (J.LeInt, targetint n, cx) in ( never1 && never2 , Js_simpl.if_statement diff --git a/compiler/lib/generate_closure.ml b/compiler/lib/generate_closure.ml index 126df9397f..b6b22a05e6 100644 --- a/compiler/lib/generate_closure.ml +++ b/compiler/lib/generate_closure.ml @@ -108,7 +108,9 @@ module Trampoline = struct let counter_plus_1 = Code.Var.fork counter in { params = [] ; body = - [ ( Let (counter_plus_1, Prim (Extern "%int_add", [ Pv counter; Pc (Int 1l) ])) + [ ( Let + ( counter_plus_1 + , Prim (Extern "%int_add", [ Pv counter; Pc (Int Targetint.one) ]) ) , noloc ) ; Let (return, Apply { f; args = counter_plus_1 :: args; exact = true }), loc ] @@ -122,8 +124,9 @@ module Trampoline = struct ; body = [ ( Let ( new_args - , Prim (Extern "%js_array", Pc (Int 0l) :: List.map args ~f:(fun x -> Pv x)) - ) + , Prim + ( Extern "%js_array" + , Pc (Int Targetint.zero) :: List.map args ~f:(fun x -> Pv x) ) ) , noloc ) ; Let (return, Prim (Extern "caml_trampoline_return", [ Pv f; Pv new_args ])), loc ] @@ -142,7 +145,7 @@ module Trampoline = struct ; Let (result2, Prim (Extern "caml_trampoline", [ Pv result1 ])), noloc ] | Some counter -> - [ Let (counter, Constant (Int 0l)), noloc + [ Let (counter, Constant (Int Targetint.zero)), noloc ; Let (result1, Apply { f; args = counter :: args; exact = true }), loc ; Let (result2, Prim (Extern "caml_trampoline", [ Pv result1 ])), noloc ]) @@ -244,7 +247,9 @@ module Trampoline = struct , Prim ( Lt , [ Pv counter - ; Pc (Int (Int32.of_int tailcall_max_depth)) + ; Pc + (Int + (Targetint.of_int_exn tailcall_max_depth)) ] ) ) , noloc ) in diff --git a/compiler/lib/global_deadcode.ml b/compiler/lib/global_deadcode.ml index c9d350b8d1..80136bc6f4 100644 --- a/compiler/lib/global_deadcode.ml +++ b/compiler/lib/global_deadcode.ml @@ -546,7 +546,7 @@ end (** Add a sentinal variable declaration to the IR. The fresh variable is assigned to `undefined`. *) let add_sentinal p sentinal = - let instr, loc = Let (sentinal, Constant (Int 0l)), noloc in + let instr, loc = Let (sentinal, Constant (Int Targetint.zero)), noloc in Code.prepend p [ instr, loc ] (** Run the liveness analysis and replace dead variables with the given sentinal. *) diff --git a/compiler/lib/javascript.ml b/compiler/lib/javascript.ml index 1a13813fe1..952b196769 100644 --- a/compiler/lib/javascript.ml +++ b/compiler/lib/javascript.ml @@ -26,13 +26,13 @@ module Num : sig val of_string_unsafe : string -> t - val of_int32 : int32 -> t + val of_targetint : Targetint.t -> t val of_float : float -> t val to_string : t -> string - val to_int32 : t -> int32 + val to_targetint : t -> Targetint.t (** Predicates *) @@ -54,17 +54,17 @@ end = struct let to_string s = s - let to_int32 s = + let to_targetint s = if String.is_prefix s ~prefix:"0" && String.length s > 1 && String.for_all s ~f:(function | '0' .. '7' -> true | _ -> false) then (* legacy octal notation *) - Int32.of_string ("0o" ^ s) - else Int32.of_string s + Targetint.of_string_exn ("0o" ^ s) + else Targetint.of_string_exn s - let of_int32 = Int32.to_string + let of_targetint = Targetint.to_string external format_float : string -> float -> string = "caml_format_float" @@ -138,7 +138,7 @@ end = struct | None -> "-" ^ s | Some s -> s - let add a b = of_int32 (Int32.add (to_int32 a) (to_int32 b)) + let add a b = of_targetint (Targetint.add (to_targetint a) (to_targetint b)) end module Label = struct diff --git a/compiler/lib/javascript.mli b/compiler/lib/javascript.mli index 2ad6e2e182..af02260783 100644 --- a/compiler/lib/javascript.mli +++ b/compiler/lib/javascript.mli @@ -27,13 +27,13 @@ module Num : sig val of_string_unsafe : string -> t - val of_int32 : int32 -> t + val of_targetint : Targetint.t -> t val of_float : float -> t val to_string : t -> string - val to_int32 : t -> int32 + val to_targetint : t -> Targetint.t (** Predicates *) diff --git a/compiler/lib/macro.ml b/compiler/lib/macro.ml index c9e9fb2047..640f355b22 100644 --- a/compiler/lib/macro.ml +++ b/compiler/lib/macro.ml @@ -35,8 +35,8 @@ class macro_mapper ~flags = | "FLAG", [ J.Arg (J.EStr (Utf8 s)) ] -> ( match flags with | Replace -> - let i = if Config.Flag.find s then 1l else 0l in - J.ENum (J.Num.of_int32 i) + let i = if Config.Flag.find s then Targetint.one else Targetint.zero in + J.ENum (J.Num.of_targetint i) | Count count -> incr count; super#expression x) @@ -44,7 +44,7 @@ class macro_mapper ~flags = when List.for_all args ~f:(function | J.Arg _ -> true | J.ArgSpread _ -> false) -> - let tag = Int32.to_int (J.Num.to_int32 tag) in + let tag = Targetint.to_int_exn (J.Num.to_targetint tag) in let args = List.map args ~f:(function | J.Arg e -> J.Element (m#expression e) @@ -54,7 +54,7 @@ class macro_mapper ~flags = | "TAG", [ J.Arg e ] -> Mlvalue.Block.tag (m#expression e) | "LENGTH", [ J.Arg e ] -> Mlvalue.Array.length (m#expression e) | "FIELD", [ J.Arg e; J.Arg (J.ENum n) ] -> - let idx = Int32.to_int (J.Num.to_int32 n) in + let idx = Targetint.to_int_exn (J.Num.to_targetint n) in Mlvalue.Block.field (m#expression e) idx | "FIELD", [ _; J.Arg (J.EUn (J.Neg, _)) ] -> failwith "Negative field indexes are not allowed" diff --git a/compiler/lib/mlvalue.ml b/compiler/lib/mlvalue.ml index 6752522408..4e2412c680 100644 --- a/compiler/lib/mlvalue.ml +++ b/compiler/lib/mlvalue.ml @@ -20,9 +20,9 @@ open! Stdlib module J = Javascript -let zero = J.ENum (J.Num.of_int32 0l) +let zero = J.ENum (J.Num.of_targetint Targetint.zero) -let one = J.ENum (J.Num.of_int32 1l) +let one = J.ENum (J.Num.of_targetint Targetint.one) (* JavaScript engines recognize the pattern 'typeof x==="number"'; if the string is shared, less efficient code is generated. *) @@ -35,13 +35,13 @@ let is_immediate e = type_of_is_number J.EqEqEq e module Block = struct let make ~tag ~args = - let tag_elt = J.Element (J.ENum (J.Num.of_int32 (Int32.of_int tag))) in + let tag_elt = J.Element (J.ENum (J.Num.of_targetint (Targetint.of_int_exn tag))) in J.EArr (tag_elt :: args) let tag e = J.EAccess (e, ANormal, zero) let field e idx = - let adjusted = J.ENum (J.Num.of_int32 (Int32.of_int (idx + 1))) in + let adjusted = J.ENum (J.Num.of_targetint (Targetint.of_int_exn (idx + 1))) in J.EAccess (e, ANormal, adjusted) end @@ -55,8 +55,8 @@ module Array = struct let field e i = match i with | J.ENum n -> - let idx = J.Num.to_int32 n in - let adjusted = J.ENum (J.Num.of_int32 (Int32.add idx 1l)) in + let idx = J.Num.to_targetint n in + let adjusted = J.ENum (J.Num.of_targetint (Targetint.succ idx)) in J.EAccess (e, ANormal, adjusted) | J.EUn (J.Neg, _) -> failwith "Negative field indexes are not allowed" | _ -> diff --git a/compiler/lib/ocaml_compiler.ml b/compiler/lib/ocaml_compiler.ml index ba16dae2a4..bad5b3cd89 100644 --- a/compiler/lib/ocaml_compiler.ml +++ b/compiler/lib/ocaml_compiler.ml @@ -22,34 +22,26 @@ let rec constant_of_const c : Code.constant = let open Lambda in let open Asttypes in match c with - | Const_base (Const_int i) -> - Int - (match Config.target () with - | `JavaScript -> Int32.of_int_warning_on_overflow i - | `Wasm -> Int31.(of_int_warning_on_overflow i |> to_int32)) - | Const_base (Const_char c) -> Int (Int32.of_int (Char.code c)) + | Const_base (Const_int i) -> Int (Targetint.of_int_warning_on_overflow i) + | Const_base (Const_char c) -> Int (Targetint.of_int_exn (Char.code c)) | ((Const_base (Const_string (s, _))) [@if ocaml_version < (4, 11, 0)]) | ((Const_base (Const_string (s, _, _))) [@if ocaml_version >= (4, 11, 0)]) -> String s | Const_base (Const_float s) -> Float (float_of_string s) | Const_base (Const_int32 i) -> ( match Config.target () with - | `JavaScript -> Int i + | `JavaScript -> Int (Targetint.of_int32_warning_on_overflow i) | `Wasm -> Int32 i) | Const_base (Const_int64 i) -> Int64 i | Const_base (Const_nativeint i) -> ( - let i = Int32.of_nativeint_warning_on_overflow i in match Config.target () with - | `JavaScript -> Int i - | `Wasm -> NativeInt i) + | `JavaScript -> Int (Targetint.of_nativeint_warning_on_overflow i) + | `Wasm -> NativeInt (Int32.of_nativeint_warning_on_overflow i)) | Const_immstring s -> String s | Const_float_array sl -> let l = List.map ~f:(fun f -> float_of_string f) sl in Float_array (Array.of_list l) | ((Const_pointer i) [@if ocaml_version < (4, 12, 0)]) -> - Int - (match Config.target () with - | `JavaScript -> Int32.of_int_warning_on_overflow i - | `Wasm -> Int31.(of_int_warning_on_overflow i |> to_int32)) + Int (Targetint.of_int_warning_on_overflow i) | Const_block (tag, l) -> let l = Array.of_list (List.map l ~f:constant_of_const) in Tuple (tag, l, Unknown) diff --git a/compiler/lib/parse_bytecode.ml b/compiler/lib/parse_bytecode.ml index c8e7cfc5d3..2068d2d233 100644 --- a/compiler/lib/parse_bytecode.ml +++ b/compiler/lib/parse_bytecode.ml @@ -493,14 +493,13 @@ end = struct | Some name when same_ident name ident_32 -> ( let i : int32 = Obj.magic x in match Config.target () with - | `JavaScript -> Int i + | `JavaScript -> Int (Targetint.of_int32_warning_on_overflow i) | `Wasm -> Int32 i) | Some name when same_ident name ident_native -> ( let i : nativeint = Obj.magic x in - let i = Int32.of_nativeint_warning_on_overflow i in match Config.target () with - | `JavaScript -> Int i - | `Wasm -> NativeInt i) + | `JavaScript -> Int (Targetint.of_nativeint_warning_on_overflow i) + | `Wasm -> NativeInt (Int32.of_nativeint_warning_on_overflow i)) | Some name when same_ident name ident_64 -> Int64 (Obj.magic x : int64) | Some name -> failwith @@ -514,10 +513,7 @@ end = struct else assert false else let i : int = Obj.magic x in - Int - (match Config.target () with - | `JavaScript -> Int32.of_int_warning_on_overflow i - | `Wasm -> Int31.(of_int_warning_on_overflow i |> to_int32)) + Int (Targetint.of_int_warning_on_overflow i) let inlined = function | String _ | NativeString _ -> false @@ -529,7 +525,9 @@ end = struct | Int32 _ | NativeInt _ -> false end -let const i = Constant (Int i) +let const32 i = Constant (Int (Targetint.of_int32_exn i)) + +let const i = Constant (Int (Targetint.of_int_exn i)) (* Globals *) type globals = @@ -808,7 +806,7 @@ let register_global ?(force = false) g i loc rem = ( Var.fresh () , Prim ( Extern "caml_register_global" - , Pc (Int (Int32.of_int i)) :: Pv (access_global g i) :: args ) ) + , Pc (Int (Targetint.of_int_exn i)) :: Pv (access_global g i) :: args ) ) , loc ) :: rem | false, false, (`JavaScript | `Wasm) -> rem @@ -1087,7 +1085,7 @@ and compile infos pc state instrs = *) List.fold_left state.handlers - ~init:((Let (x, const 0l), loc) :: instrs) + ~init:((Let (x, const 0), loc) :: instrs) ~f:(fun acc (handler : State.handler) -> let handler_stack_size = List.length handler.stack in let diff = stack_size - handler_stack_size in @@ -1433,7 +1431,7 @@ and compile infos pc state instrs = let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = 0@." Var.print x; let instrs = register_global g i loc instrs in - compile infos (pc + 2) state ((Let (x, const 0l), loc) :: instrs) + compile infos (pc + 2) state ((Let (x, const 0), loc) :: instrs) | ATOM0 -> let x, state = State.fresh_var state loc in @@ -1622,7 +1620,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 0, Non_float, z), loc) :: instrs) + ((Let (x, const 0), loc) :: (Set_field (y, 0, Non_float, z), loc) :: instrs) | SETFIELD1 -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1634,7 +1632,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 1, Non_float, z), loc) :: instrs) + ((Let (x, const 0), loc) :: (Set_field (y, 1, Non_float, z), loc) :: instrs) | SETFIELD2 -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1646,7 +1644,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 2, Non_float, z), loc) :: instrs) + ((Let (x, const 0), loc) :: (Set_field (y, 2, Non_float, z), loc) :: instrs) | SETFIELD3 -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1658,7 +1656,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 3, Non_float, z), loc) :: instrs) + ((Let (x, const 0), loc) :: (Set_field (y, 3, Non_float, z), loc) :: instrs) | SETFIELD -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1671,7 +1669,7 @@ and compile infos pc state instrs = infos (pc + 2) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, n, Non_float, z), loc) :: instrs) + ((Let (x, const 0), loc) :: (Set_field (y, n, Non_float, z), loc) :: instrs) | SETFLOATFIELD -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1685,7 +1683,7 @@ and compile infos pc state instrs = infos (pc + 2) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, n, Float, z), loc) :: instrs) + ((Let (x, const 0), loc) :: (Set_field (y, n, Float, z), loc) :: instrs) | VECTLENGTH -> let y, _ = State.accu state in let x, state = State.fresh_var state loc in @@ -1717,7 +1715,7 @@ and compile infos pc state instrs = let instrs = (Array_set (x, y, z), loc) :: instrs in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = 0@." Var.print x; - compile infos (pc + 1) (State.pop 2 state) ((Let (x, const 0l), loc) :: instrs) + compile infos (pc + 1) (State.pop 2 state) ((Let (x, const 0), loc) :: instrs) | GETSTRINGCHAR -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1756,7 +1754,7 @@ and compile infos pc state instrs = in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = 0@." Var.print x; - compile infos (pc + 1) (State.pop 2 state) ((Let (x, const 0l), loc) :: instrs) + compile infos (pc + 1) (State.pop 2 state) ((Let (x, const 0), loc) :: instrs) | BRANCH -> let offset = gets code (pc + 1) in if debug_parser () then Format.printf "... (branch)@."; @@ -2020,34 +2018,34 @@ and compile infos pc state instrs = let x, state = State.fresh_var state loc in let n = match cc with - | CONST0 -> 0l - | CONST1 -> 1l - | CONST2 -> 2l - | CONST3 -> 3l + | CONST0 -> 0 + | CONST1 -> 1 + | CONST2 -> 2 + | CONST3 -> 3 | _ -> assert false in - if debug_parser () then Format.printf "%a = %ld@." Var.print x n; + if debug_parser () then Format.printf "%a = %d@." Var.print x n; compile infos (pc + 1) state ((Let (x, const n), loc) :: instrs) | CONSTINT -> let n = gets32 code (pc + 1) in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %ld@." Var.print x n; - compile infos (pc + 2) state ((Let (x, const n), loc) :: instrs) + compile infos (pc + 2) state ((Let (x, const32 n), loc) :: instrs) | (PUSHCONST0 | PUSHCONST1 | PUSHCONST2 | PUSHCONST3) as cc -> let state = State.push state loc in let x, state = State.fresh_var state loc in let n = match cc with - | PUSHCONST0 -> 0l - | PUSHCONST1 -> 1l - | PUSHCONST2 -> 2l - | PUSHCONST3 -> 3l + | PUSHCONST0 -> 0 + | PUSHCONST1 -> 1 + | PUSHCONST2 -> 2 + | PUSHCONST3 -> 3 | _ -> assert false in - if debug_parser () then Format.printf "%a = %ld@." Var.print x n; + if debug_parser () then Format.printf "%a = %d@." Var.print x n; compile infos (pc + 1) state ((Let (x, const n), loc) :: instrs) | PUSHCONSTINT -> let state = State.push state loc in @@ -2055,7 +2053,7 @@ and compile infos pc state instrs = let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %ld@." Var.print x n; - compile infos (pc + 2) state ((Let (x, const n), loc) :: instrs) + compile infos (pc + 2) state ((Let (x, const32 n), loc) :: instrs) | NEGINT -> let y, _ = State.accu state in let x, state = State.fresh_var state loc in @@ -2282,7 +2280,7 @@ and compile infos pc state instrs = (pc + 2) state ((Let (x, Prim (Extern "%int_add", [ Pv y; Pv z ])), loc) - :: (Let (z, const n), loc) + :: (Let (z, const32 n), loc) :: instrs) | OFFSETREF -> let n = gets code (pc + 1) in @@ -2292,7 +2290,7 @@ and compile infos pc state instrs = let instrs = (Offset_ref (x, n), loc) :: instrs in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "x = 0@."; - compile infos (pc + 2) state ((Let (x, const 0l), loc) :: instrs) + compile infos (pc + 2) state ((Let (x, const 0), loc) :: instrs) | ISINT -> let y, _ = State.accu state in let x, state = State.fresh_var state loc in @@ -2305,7 +2303,8 @@ and compile infos pc state instrs = let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Eq, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Eq, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + offset + 2, []), (pc + 3, [])), loc) , state ) | BNEQ -> @@ -2314,7 +2313,8 @@ and compile infos pc state instrs = let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Eq, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Eq, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + 3, []), (pc + offset + 2, [])), loc) , state ) | BLTINT -> @@ -2323,7 +2323,8 @@ and compile infos pc state instrs = let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Lt, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Lt, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + offset + 2, []), (pc + 3, [])), loc) , state ) | BLEINT -> @@ -2332,7 +2333,8 @@ and compile infos pc state instrs = let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Le, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Le, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + offset + 2, []), (pc + 3, [])), loc) , state ) | BGTINT -> @@ -2341,7 +2343,8 @@ and compile infos pc state instrs = let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Le, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Le, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + 3, []), (pc + offset + 2, [])), loc) , state ) | BGEINT -> @@ -2350,7 +2353,8 @@ and compile infos pc state instrs = let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Lt, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Lt, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + 3, []), (pc + offset + 2, [])), loc) , state ) | BULTINT -> @@ -2359,7 +2363,8 @@ and compile infos pc state instrs = let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Ult, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Ult, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + offset + 2, []), (pc + 3, [])), loc) , state ) | BUGEINT -> @@ -2367,7 +2372,8 @@ and compile infos pc state instrs = let offset = gets code (pc + 2) in let x, _ = State.accu state in let y = Var.fresh () in - ( (Let (y, Prim (Ult, [ Pc (Int n); Pv x ])), loc) :: instrs + ( (Let (y, Prim (Ult, [ Pc (Int (Targetint.of_int32_exn n)); Pv x ])), loc) + :: instrs , (Cond (y, (pc + 3, []), (pc + offset + 2, [])), loc) , state ) | ULTINT -> @@ -2430,9 +2436,9 @@ and compile infos pc state instrs = ( m , Prim ( Extern "caml_get_public_method" - , [ Pv obj; Pv tag; Pc (Int (Int32.of_int cache)) ] ) ) + , [ Pv obj; Pv tag; Pc (Int (Targetint.of_int_exn cache)) ] ) ) , loc ) - :: (Let (tag, const n), loc) + :: (Let (tag, const32 n), loc) :: instrs) | GETDYNMET -> let tag, _ = State.accu state in @@ -2454,7 +2460,10 @@ and compile infos pc state instrs = (pc + 1) state (( Let - (m, Prim (Extern "caml_get_public_method", [ Pv obj; Pv tag; Pc (Int 0l) ])) + ( m + , Prim + ( Extern "caml_get_public_method" + , [ Pv obj; Pv tag; Pc (Int Targetint.zero) ] ) ) , loc ) :: instrs) | GETMETHOD -> @@ -2794,7 +2803,7 @@ let from_exe let infos = [ "sections", Constants.parse (Obj.repr sections) ; "symbols", Constants.parse (Obj.repr symbols_array) - ; "prim_count", Int (Int32.of_int (Array.length globals.primitives)) + ; "prim_count", Int (Targetint.of_int_exn (Array.length globals.primitives)) ] in let body = @@ -3169,7 +3178,7 @@ let predefined_exceptions () = (Int ((* Predefined exceptions are registered in Symtable.init with [-index - 1] *) - Int32.of_int + Targetint.of_int_exn (-index - 1))) ) , noloc ) ; Let (exn, Block (248, [| v_name; v_index |], NotArray, Immutable)), noloc @@ -3184,7 +3193,8 @@ let predefined_exceptions () = ( Var.fresh () , Prim ( Extern "caml_register_global" - , [ Pc (Int (Int32.of_int index)); Pv exn; Pv v_name_js ] ) ) + , [ Pc (Int (Targetint.of_int_exn index)); Pv exn; Pv v_name_js ] ) + ) , noloc ) ] | `Wasm -> @@ -3192,7 +3202,7 @@ let predefined_exceptions () = ( Var.fresh () , Prim ( Extern "caml_register_global" - , [ Pc (Int (Int32.of_int index)); Pv exn; Pv v_name ] ) ) + , [ Pc (Int (Targetint.of_int_exn index)); Pv exn; Pv v_name ] ) ) , noloc ) (* Also make the exception available to the generated code *) ; ( Let @@ -3234,7 +3244,7 @@ let link_info ~symbols ~primitives ~crcs = let infos = [ "sections", Constants.parse (Obj.repr sections) ; "symbols", Constants.parse (Obj.repr symbols_array) - ; "prim_count", Int (Int32.of_int (List.length primitives)) + ; "prim_count", Int (Targetint.of_int_exn (List.length primitives)) ] in let body = diff --git a/compiler/lib/specialize_js.ml b/compiler/lib/specialize_js.ml index 106a86ce06..3e75f1a1f8 100644 --- a/compiler/lib/specialize_js.ml +++ b/compiler/lib/specialize_js.ml @@ -31,12 +31,12 @@ let specialize_instr ~target info i = match the_string_of ~target info y with | Some "%d" -> ( match the_int ~target info z with - | Some i -> Let (x, Constant (String (Int32.to_string i))) + | Some i -> Let (x, Constant (String (Targetint.to_string i))) | None -> Let (x, Prim (Extern "%caml_format_int_special", [ z ]))) | _ -> i) | Let (x, Prim (Extern "%caml_format_int_special", [ z ])), `JavaScript -> ( match the_int ~target info z with - | Some i -> Let (x, Constant (String (Int32.to_string i))) + | Some i -> Let (x, Constant (String (Targetint.to_string i))) | None -> i) (* inline the String constant argument so that generate.ml can attempt to parse it *) | ( Let @@ -52,7 +52,7 @@ let specialize_instr ~target info i = match the_string_of ~target info y with | Some s when Primitive.need_named_value s -> Let (x, Prim (Extern prim, [ Pc (String s); z ])) - | Some _ -> Let (x, Constant (Int 0l)) + | Some _ -> Let (x, Constant (Int Targetint.zero)) | None -> i) | Let (x, Prim (Extern "caml_js_call", [ f; o; a ])), _ -> ( match the_def_of info a with @@ -135,22 +135,25 @@ let specialize_instr ~target info i = | Some s -> Let (x, Constant (NativeString (Native_string.of_bytestring s))) | None -> i) | Let (x, Prim (Extern "%int_mul", [ y; z ])), `JavaScript -> ( + let limit = Targetint.of_int_exn 0x200000 in (* Using * to multiply integers in JavaScript yields a float; and if the - float is large enough, some bits can be lost. So, in the general case, - we have to use Math.imul. There is no such issue in Wasm. *) + float is large enough, some bits can be lost. So, in the general case, + we have to use Math.imul. There is no such issue in Wasm. *) match the_int ~target info y, the_int ~target info z with - | Some j, _ when Int32.(abs j < 0x200000l) -> + | Some j, _ when Targetint.(abs j < limit) -> Let (x, Prim (Extern "%direct_int_mul", [ y; z ])) - | _, Some j when Int32.(abs j < 0x200000l) -> + | _, Some j when Targetint.(abs j < limit) -> Let (x, Prim (Extern "%direct_int_mul", [ y; z ])) | _ -> i) | Let (x, Prim (Extern "%int_div", [ y; z ])), _ -> ( match the_int ~target info z with - | Some j when Int32.(j <> 0l) -> Let (x, Prim (Extern "%direct_int_div", [ y; z ])) + | Some j when not (Targetint.is_zero j) -> + Let (x, Prim (Extern "%direct_int_div", [ y; z ])) | _ -> i) | Let (x, Prim (Extern "%int_mod", [ y; z ])), _ -> ( match the_int ~target info z with - | Some j when Int32.(j <> 0l) -> Let (x, Prim (Extern "%direct_int_mod", [ y; z ])) + | Some j when not (Targetint.is_zero j) -> + Let (x, Prim (Extern "%direct_int_mod", [ y; z ])) | _ -> i) | _, _ -> i @@ -172,17 +175,20 @@ let specialize_instrs ~target info l = ( u1 , Prim ( Extern "caml_blit_string" - , [ Pv a'; Pc (Int 0l); Pv bytes'; Pc (Int 0l); Pv alen'' ] ) ) + , [ Pv a'; Pc (Int zero1); Pv bytes'; Pc (Int zero2); Pv alen'' ] ) ) , _ ) ; ( Let ( u2 , Prim ( Extern "caml_blit_string" - , [ Pv b'; Pc (Int 0l); Pv bytes''; Pv alen'''; Pv blen'' ] ) ) + , [ Pv b'; Pc (Int zero3); Pv bytes''; Pv alen'''; Pv blen'' ] ) ) , _ ) ; (Let (res, Prim (Extern "caml_string_of_bytes", [ Pv bytes''' ])), _) ] - when equal2 a a' + when Targetint.is_zero zero1 + && Targetint.is_zero zero2 + && Targetint.is_zero zero3 + && equal2 a a' && equal2 b b' && equal2 len len' && equal4 alen alen' alen'' alen''' @@ -191,8 +197,8 @@ let specialize_instrs ~target info l = [ len1 ; len2 ; len3 - ; Let (u1, Constant (Int 0l)), No - ; Let (u2, Constant (Int 0l)), No + ; Let (u1, Constant (Int Targetint.zero)), No + ; Let (u2, Constant (Int Targetint.zero)), No ; Let (res, Prim (Extern "caml_string_concat", [ Pv a; Pv b ])), No ; Let (bytes, Prim (Extern "caml_bytes_of_string", [ Pv res ])), No ] @@ -325,7 +331,9 @@ let f_once p = | "caml_floatarray_unsafe_set" ) , [ _; _; _ ] ) as p) ) -> let x' = Code.Var.fork x in - let acc = (Let (x', p), loc) :: (Let (x, Constant (Int 0l)), loc) :: acc in + let acc = + (Let (x', p), loc) :: (Let (x, Constant (Int Targetint.zero)), loc) :: acc + in loop acc r | _ -> loop ((i, loc) :: acc) r) in diff --git a/compiler/lib/stdlib.ml b/compiler/lib/stdlib.ml index bb01e08dab..42c2dd05cd 100644 --- a/compiler/lib/stdlib.ml +++ b/compiler/lib/stdlib.ml @@ -322,15 +322,6 @@ module Int32 = struct if not (equal x' x) then warn_overflow ~to_dec ~to_hex x i32; i32 - let of_int_warning_on_overflow i = - convert_warning_on_overflow - ~to_int32:Int32.of_int - ~of_int32:Int32.to_int - ~equal:Int_replace_polymorphic_compare.( = ) - ~to_dec:(Printf.sprintf "%d") - ~to_hex:(Printf.sprintf "%x") - i - let of_nativeint_warning_on_overflow n = convert_warning_on_overflow ~to_int32:Nativeint.to_int32 @@ -341,118 +332,6 @@ module Int32 = struct n end -module type Arith_ops = sig - type t - - val neg : t -> t - - val add : t -> t -> t - - val sub : t -> t -> t - - val mul : t -> t -> t - - val div : t -> t -> t - - val rem : t -> t -> t - - val logand : t -> t -> t - - val logor : t -> t -> t - - val logxor : t -> t -> t - - val shift_left : t -> int -> t - - val shift_right : t -> int -> t - - val shift_right_logical : t -> int -> t -end - -module Int31 : sig - type t - - include Arith_ops with type t := t - - val of_int_warning_on_overflow : int -> t - - val of_nativeint_warning_on_overflow : nativeint -> t - - val of_int32_warning_on_overflow : int32 -> t - - val to_int32 : t -> int32 -end = struct - type t = int32 - - let wrap i = Int32.(shift_right (shift_left i 1) 1) - - let of_int_warning_on_overflow i = - Int32.convert_warning_on_overflow - ~to_int32:(fun i -> wrap (Int32.of_int i)) - ~of_int32:Int32.to_int - ~equal:Int_replace_polymorphic_compare.( = ) - ~to_dec:(Printf.sprintf "%d") - ~to_hex:(Printf.sprintf "%x") - i - - let of_nativeint_warning_on_overflow n = - Int32.convert_warning_on_overflow - ~to_int32:(fun i -> wrap (Nativeint.to_int32 i)) - ~of_int32:Nativeint.of_int32 - ~equal:Nativeint.equal - ~to_dec:(Printf.sprintf "%nd") - ~to_hex:(Printf.sprintf "%nx") - n - - let of_int32_warning_on_overflow n = - Int32.convert_warning_on_overflow - ~to_int32:(fun i -> wrap i) - ~of_int32:Fun.id - ~equal:Int32.equal - ~to_dec:(Printf.sprintf "%ld") - ~to_hex:(Printf.sprintf "%lx") - n - - let two_pow n = - assert (0 <= n && n <= 31); - Int32.shift_left 1l n - - let min_int = Int32.neg (two_pow 30) - - let neg x = if Int32.equal x min_int then x else Int32.neg x - - let int_binop f x y = wrap (f x y) - - let add = int_binop Int32.add - - let sub = int_binop Int32.sub - - let mul = int_binop Int32.mul - - let div = int_binop Int32.div - - let rem = int_binop Int32.rem - - let logand = int_binop Int32.logand - - let logor = int_binop Int32.logor - - let logxor = int_binop Int32.logxor - - let shift_op f x y = - (* Limit the shift offset to [0, 31] *) - wrap (f x (y land 0x1f)) - - let shift_left = shift_op Int32.shift_left - - let shift_right = shift_op Int32.shift_right - - let shift_right_logical a b = - shift_op Int32.shift_right_logical (Int32.logand a 0x7fffffffl) b - - let to_int32 (x : t) : int32 = x -end - module Option = struct let map ~f x = match x with diff --git a/compiler/lib/targetint.ml b/compiler/lib/targetint.ml new file mode 100644 index 0000000000..635efef14e --- /dev/null +++ b/compiler/lib/targetint.ml @@ -0,0 +1,163 @@ +type t = Int32.t + +let num_bits_ = ref 0 + +let set_num_bits x = num_bits_ := x + +let num_bits () = + match !num_bits_ with + | (31 | 32) as x -> x + | x -> failwith (Printf.sprintf "Targetint.num_bits %d unsupported" x) + +type offset = Offset of int [@@ocaml.unboxed] + +let () = assert (Obj.is_int (Obj.repr (Offset 0))) + +let offset () = Offset (32 - num_bits ()) + +let equal = Int32.equal + +let compare = Int32.compare + +let wrap (Offset offset) i = Int32.(shift_left i offset) + +let unwrap (Offset offset) i = Int32.(shift_right i offset) + +let wrap_modulo i = + let offset = offset () in + unwrap offset (wrap offset i) + +let max_int_ (Offset offset) = Int32.shift_right Int32.max_int offset + +let min_int_ (Offset offset) = Int32.shift_right Int32.min_int offset + +let min_int_i offset = Int32.to_int (min_int_ offset) + +let max_int_i offset = Int32.to_int (max_int_ offset) + +let min_int () = + let offset = offset () in + min_int_ offset + +let max_int () = + let offset = offset () in + max_int_ offset + +let to_string x = Int32.to_string x + +let to_float x = Int32.to_float x + +let to_int32 x = x + +let to_int_exn x = + if Sys.int_size <= 32 || Int32.of_int Int.min_int <= x || x <= Int32.of_int Int.max_int + then Int32.to_int x + else failwith "to_int_exn" + +let neg x = + let offset = offset () in + unwrap offset (Int32.neg (wrap offset x)) + +let abs x = + let offset = offset () in + unwrap offset (Int32.abs (wrap offset x)) + +let int_binop f x y = wrap_modulo (f x y) + +let add = int_binop Int32.add + +let zero = 0l + +let one = 1l + +let succ x = add x one + +let sub = int_binop Int32.sub + +let mul = int_binop Int32.mul + +let div = int_binop Int32.div + +let rem = int_binop Int32.rem + +let logand = int_binop Int32.logand + +let logor = int_binop Int32.logor + +let logxor = int_binop Int32.logxor + +let shift_op f x y = + let offset = offset () in + (* Limit the shift offset to [0, 31], this works for both 31 and 32 + bit integers *) + unwrap offset (f (wrap offset x) (y land 0x1f)) + +let shift_left = shift_op Int32.shift_left + +let shift_right = shift_op Int32.shift_right + +let shift_right_logical = shift_op Int32.shift_right_logical + +let is_zero x = equal x 0l + +let of_int_exn (x : int) = + let offset = offset () in + if min_int_i offset <= x && x <= max_int_i offset + then Int32.of_int x + else failwith "of_int_exn" + +let of_int32_exn (x : int32) = + let offset = offset () in + if min_int_ offset <= x && x <= max_int_ offset then x else failwith "of_int32_exn" + +let of_string_exn x = + try + let offset = offset () in + let x32 = Int32.of_string x in + if min_int_ offset <= x32 || x32 <= max_int_ offset then x32 else raise Not_found + with Not_found | _ -> failwith (Printf.sprintf "Targetint.of_string_exn(%s)" x) + +let of_float_opt x = + let offset = offset () in + if Int32.to_float (min_int_ offset) <= x || x <= Int32.to_float (max_int_ offset) + then Some (wrap_modulo (Int32.of_float x)) + else None + +let of_int_warning_on_overflow i = + Stdlib.Int32.convert_warning_on_overflow + ~to_int32:(fun i -> wrap_modulo (Int32.of_int i)) + ~of_int32:Int32.to_int + ~equal:Int.equal + ~to_dec:(Printf.sprintf "%d") + ~to_hex:(Printf.sprintf "%x") + i + +let of_int32_warning_on_overflow n = + Stdlib.Int32.convert_warning_on_overflow + ~to_int32:(fun i -> wrap_modulo i) + ~of_int32:Fun.id + ~equal:Int32.equal + ~to_dec:(Printf.sprintf "%ld") + ~to_hex:(Printf.sprintf "%lx") + n + +let of_nativeint_warning_on_overflow n = + Stdlib.Int32.convert_warning_on_overflow + ~to_int32:(fun i -> wrap_modulo (Nativeint.to_int32 i)) + ~of_int32:Nativeint.of_int32 + ~equal:Nativeint.equal + ~to_dec:(Printf.sprintf "%nd") + ~to_hex:(Printf.sprintf "%nx") + n + +external ( < ) : int32 -> int32 -> bool = "%lessthan" + +external ( <= ) : int32 -> int32 -> bool = "%lessequal" + +external ( <> ) : int32 -> int32 -> bool = "%notequal" + +external ( = ) : int32 -> int32 -> bool = "%equal" + +external ( > ) : int32 -> int32 -> bool = "%greaterthan" + +external ( >= ) : int32 -> int32 -> bool = "%greaterequal" diff --git a/compiler/lib/targetint.mli b/compiler/lib/targetint.mli new file mode 100644 index 0000000000..15fd1846ff --- /dev/null +++ b/compiler/lib/targetint.mli @@ -0,0 +1,93 @@ +type t + +val equal : t -> t -> bool + +val compare : t -> t -> int + +val is_zero : t -> bool + +(* to *) + +val to_string : t -> string + +val to_int_exn : t -> int + +val to_float : t -> float + +val to_int32 : t -> int32 + +(* of *) + +val of_string_exn : string -> t + +val of_int_exn : int -> t + +val of_int32_exn : int32 -> t + +val of_int32_warning_on_overflow : int32 -> t + +val of_nativeint_warning_on_overflow : nativeint -> t + +val of_int_warning_on_overflow : int -> t + +val of_float_opt : float -> t option + +(* arithmetic *) + +val succ : t -> t + +val add : t -> t -> t + +val sub : t -> t -> t + +val mul : t -> t -> t + +val div : t -> t -> t + +val rem : t -> t -> t + +val logand : t -> t -> t + +val logor : t -> t -> t + +val logxor : t -> t -> t + +val shift_left : t -> int -> t + +val shift_right : t -> int -> t + +val shift_right_logical : t -> int -> t + +val neg : t -> t + +val abs : t -> t + +(* constant *) + +val min_int : unit -> t + +val max_int : unit -> t + +val zero : t + +val one : t + +(* num bits *) + +val num_bits : unit -> int + +val set_num_bits : int -> unit + +(* comparison *) + +val ( >= ) : t -> t -> bool + +val ( <= ) : t -> t -> bool + +val ( < ) : t -> t -> bool + +val ( > ) : t -> t -> bool + +val ( = ) : t -> t -> bool + +val ( <> ) : t -> t -> bool diff --git a/compiler/tests-compiler/macro.ml b/compiler/tests-compiler/macro.ml index 77060e12d2..fe000c8e77 100644 --- a/compiler/tests-compiler/macro.ml +++ b/compiler/tests-compiler/macro.ml @@ -35,6 +35,7 @@ let print_macro_transformed source = print_endline (Buffer.contents buffer)) let print_macro_transformed source = + Jsoo.Targetint.set_num_bits 32; try print_macro_transformed source with Failure s -> Format.printf "failure: %s%!" s let%expect_test "BLOCK()" = diff --git a/compiler/tests-compiler/pbt/test_int31.ml b/compiler/tests-compiler/pbt/test_int31.ml index 1f6abe6d31..26211f4cd4 100644 --- a/compiler/tests-compiler/pbt/test_int31.ml +++ b/compiler/tests-compiler/pbt/test_int31.ml @@ -1,5 +1,8 @@ open! Js_of_ocaml_compiler.Stdlib open QCheck2 +module Int31 = Js_of_ocaml_compiler.Targetint + +let () = Int31.set_num_bits 31 let () = Printexc.record_backtrace false @@ -121,11 +124,11 @@ module E = struct let one = Int31.of_int32_warning_on_overflow 1l - let min_int = Int31.of_int32_warning_on_overflow min_int31 + let min_int = Int31.min_int () - let max_int = Int31.of_int32_warning_on_overflow max_int31 + let max_int = Int31.max_int () - let numbits = 31 + let numbits = Int31.num_bits () let cases = [ "zero", zero; "one", one; "-one", Int31.neg one; "min", min_int; "max", max_int ]