diff --git a/compiler/lib/code.ml b/compiler/lib/code.ml index b7143e3f2..591cac4c1 100644 --- a/compiler/lib/code.ml +++ b/compiler/lib/code.ml @@ -377,6 +377,10 @@ type mutability = | Immutable | Maybe_mutable +type field_type = + | Non_float + | Float + type expr = | Apply of { f : Var.t @@ -384,7 +388,7 @@ type expr = ; exact : bool } | Block of int * Var.t array * array_or_not * mutability - | Field of Var.t * int + | Field of Var.t * int * field_type | Closure of Var.t list * cont | Constant of constant | Prim of prim * prim_arg list @@ -393,7 +397,7 @@ type expr = type instr = | Let of Var.t * expr | Assign of Var.t * Var.t - | Set_field of Var.t * int * Var.t + | Set_field of Var.t * int * field_type * Var.t | Offset_ref of Var.t * int | Array_set of Var.t * Var.t * Var.t @@ -537,7 +541,8 @@ module Print = struct Format.fprintf f "; %d = %a" i Var.print a.(i) done; Format.fprintf f "}" - | Field (x, i) -> Format.fprintf f "%a[%d]" Var.print x i + | Field (x, i, Non_float) -> Format.fprintf f "%a[%d]" Var.print x i + | Field (x, i, Float) -> Format.fprintf f "FLOAT{%a[%d]}" Var.print x i | Closure (l, c) -> Format.fprintf f "fun(%a){%a}" var_list l cont c | Constant c -> Format.fprintf f "CONST{%a}" constant c | Prim (p, l) -> prim f p l @@ -547,7 +552,10 @@ module Print = struct match i with | Let (x, e) -> Format.fprintf f "%a = %a" Var.print x expr e | Assign (x, y) -> Format.fprintf f "(assign) %a = %a" Var.print x Var.print y - | Set_field (x, i, y) -> Format.fprintf f "%a[%d] = %a" Var.print x i Var.print y + | Set_field (x, i, Non_float, y) -> + Format.fprintf f "%a[%d] = %a" Var.print x i Var.print y + | Set_field (x, i, Float, y) -> + Format.fprintf f "FLOAT{%a[%d]} = %a" Var.print x i Var.print y | Offset_ref (x, i) -> Format.fprintf f "%a[0] += %d" Var.print x i | Array_set (x, y, z) -> Format.fprintf f "%a[%a] = %a" Var.print x Var.print y Var.print z @@ -821,7 +829,7 @@ let invariant { blocks; start; _ } = let check_expr = function | Apply _ -> () | Block (_, _, _, _) -> () - | Field (_, _) -> () + | Field (_, _, _) -> () | Closure (l, cont) -> List.iter l ~f:define; check_cont cont @@ -835,7 +843,7 @@ let invariant { blocks; start; _ } = define x; check_expr e | Assign _ -> () - | Set_field (_, _i, _) -> () + | Set_field (_, _i, _, _) -> () | Offset_ref (_x, _i) -> () | Array_set (_x, _y, _z) -> () in diff --git a/compiler/lib/code.mli b/compiler/lib/code.mli index 16af48737..6e8f0d0bd 100644 --- a/compiler/lib/code.mli +++ b/compiler/lib/code.mli @@ -191,6 +191,10 @@ type mutability = | Immutable | Maybe_mutable +type field_type = + | Non_float + | Float + type expr = | Apply of { f : Var.t @@ -198,7 +202,7 @@ type expr = ; exact : bool (* if true, then # of arguments = # of parameters *) } | Block of int * Var.t array * array_or_not * mutability - | Field of Var.t * int + | Field of Var.t * int * field_type | Closure of Var.t list * cont | Constant of constant | Prim of prim * prim_arg list @@ -207,7 +211,7 @@ type expr = type instr = | Let of Var.t * expr | Assign of Var.t * Var.t - | Set_field of Var.t * int * Var.t + | Set_field of Var.t * int * field_type * Var.t | Offset_ref of Var.t * int | Array_set of Var.t * Var.t * Var.t diff --git a/compiler/lib/deadcode.ml b/compiler/lib/deadcode.ml index ae182423f..5e7b61756 100644 --- a/compiler/lib/deadcode.ml +++ b/compiler/lib/deadcode.ml @@ -62,7 +62,7 @@ and mark_expr st e = mark_var st f; List.iter args ~f:(fun x -> mark_var st x) | Block (_, a, _, _) -> Array.iter a ~f:(fun x -> mark_var st x) - | Field (x, _) -> mark_var st x + | Field (x, _, _) -> mark_var st x | Closure (_, (pc, _)) -> mark_reachable st pc | Special _ -> () | Prim (_, l) -> @@ -82,7 +82,7 @@ and mark_reachable st pc = match i with | Let (_, e) -> if not (pure_expr st.pure_funs e) then mark_expr st e | Assign _ -> () - | Set_field (x, _, y) -> + | Set_field (x, _, _, y) -> mark_var st x; mark_var st y | Array_set (x, y, z) -> @@ -190,7 +190,7 @@ let f ({ blocks; _ } as p : Code.program) = match i with | Let (x, e) -> add_def defs x (Expr e) | Assign (x, y) -> add_def defs x (Var y) - | Set_field (_, _, _) | Array_set (_, _, _) | Offset_ref (_, _) -> ()); + | Set_field (_, _, _, _) | Array_set (_, _, _) | Offset_ref (_, _) -> ()); match fst block.branch with | Return _ | Raise _ | Stop -> () | Branch cont -> add_cont_dep blocks defs cont diff --git a/compiler/lib/eval.ml b/compiler/lib/eval.ml index e61bd48a5..d8a4e48e2 100644 --- a/compiler/lib/eval.ml +++ b/compiler/lib/eval.ml @@ -42,7 +42,7 @@ let shift l w t f = Some (Int (w (f (t i) (Int32.to_int j land 0x1f)))) | _ -> None -let float_binop_aux l f = +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) @@ -55,12 +55,12 @@ let float_binop_aux l f = | None -> None | Some (i, j) -> Some (f i j) -let float_binop l f = +let float_binop (l : constant list) (f : float -> float -> float) : constant option = match float_binop_aux l f with | Some x -> Some (Float x) | None -> None -let float_unop l f = +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))) @@ -426,10 +426,11 @@ let rec do_not_raise pc visited blocks = let b = Addr.Map.find pc blocks in List.iter b.body ~f:(fun (i, _loc) -> match i with - | Array_set (_, _, _) | Offset_ref (_, _) | Set_field (_, _, _) | Assign _ -> () + | Array_set (_, _, _) | Offset_ref (_, _) | Set_field (_, _, _, _) | Assign _ -> + () | Let (_, e) -> ( match e with - | Block (_, _, _, _) | Field (_, _) | Constant _ | Closure _ -> () + | Block (_, _, _, _) | Field (_, _, _) | Constant _ | Closure _ -> () | Apply _ -> raise May_raise | Special _ -> () | Prim (Extern name, _) when Primitive.is_pure name -> () diff --git a/compiler/lib/flow.ml b/compiler/lib/flow.ml index b5ee88b9a..f5e8193ea 100644 --- a/compiler/lib/flow.ml +++ b/compiler/lib/flow.ml @@ -94,7 +94,7 @@ let expr_deps blocks vars deps defs x e = List.iter l ~f:(fun x -> add_param_def vars defs x); cont_deps blocks vars deps defs cont | Block (_, a, _, _) -> Array.iter a ~f:(fun y -> add_dep deps x y) - | Field (y, _) -> add_dep deps x y + | Field (y, _, _) -> add_dep deps x y let program_deps { blocks; _ } = let nv = Var.count () in @@ -138,7 +138,7 @@ let propagate1 deps defs st x = match e with | Constant _ | Apply _ | Prim _ | Special _ | Closure _ | Block _ -> Var.Set.singleton x - | Field (y, n) -> + | Field (y, n, _) -> var_set_lift (fun z -> match defs.(Var.idx z) with @@ -244,7 +244,7 @@ let program_escape defs known_origins { blocks; _ } = match i with | Let (x, e) -> expr_escape st x e | Assign _ -> () - | Set_field (x, _, y) | Array_set (x, _, y) -> + | Set_field (x, _, _, y) | Array_set (x, _, y) -> Var.Set.iter (fun y -> Var.ISet.add possibly_mutable y) (Var.Tbl.get known_origins x); @@ -268,7 +268,7 @@ let propagate2 ?(skip_param = false) defs known_origins possibly_mutable st x = | Expr e -> ( match e with | Constant _ | Closure _ | Apply _ | Prim _ | Block _ | Special _ -> false - | Field (y, n) -> + | Field (y, n, _) -> Var.Tbl.get st y || Var.Set.exists (fun z -> @@ -360,7 +360,7 @@ let the_native_string_of info x = (*XXX Maybe we could iterate? *) let direct_approx info x = match info.info_defs.(Var.idx x) with - | Expr (Field (y, n)) -> + | Expr (Field (y, n, _)) -> get_approx info (fun z -> diff --git a/compiler/lib/freevars.ml b/compiler/lib/freevars.ml index fdeaa8321..b0601ccba 100644 --- a/compiler/lib/freevars.ml +++ b/compiler/lib/freevars.ml @@ -34,7 +34,7 @@ let iter_expr_free_vars f e = f x; List.iter ~f args | Block (_, a, _, _) -> Array.iter ~f a - | Field (x, _) -> f x + | Field (x, _, _) -> f x | Closure _ -> () | Special _ -> () | Prim (_, l) -> @@ -46,7 +46,7 @@ let iter_expr_free_vars f e = let iter_instr_free_vars f i = match i with | Let (_, e) -> iter_expr_free_vars f e - | Set_field (x, _, y) -> + | Set_field (x, _, _, y) -> f x; f y | Offset_ref (x, _) -> f x diff --git a/compiler/lib/generate.ml b/compiler/lib/generate.ml index 5dcf214e4..58893caae 100644 --- a/compiler/lib/generate.ml +++ b/compiler/lib/generate.ml @@ -1240,7 +1240,7 @@ let rec translate_expr ctx queue loc x e level : _ * J.statement_list = | NotArray | Unknown -> Mlvalue.Block.make ~tag ~args:contents in (x, prop, queue), [] - | Field (x, n) -> + | Field (x, n, _) -> let (px, cx), queue = access_queue queue x in (Mlvalue.Block.field cx n, or_p px mutable_p, queue), [] | Closure (args, ((pc, _) as cont)) -> @@ -1532,7 +1532,7 @@ and translate_instr ctx expr_queue instr = expr_queue prop (instrs @ [ J.variable_declaration [ J.V x, (ce, loc) ], loc ])) - | Set_field (x, n, y) -> + | Set_field (x, n, _, y) -> let loc = source_location_ctx ctx pc in let (_px, cx), expr_queue = access_queue expr_queue x in let (_py, cy), expr_queue = access_queue expr_queue y in diff --git a/compiler/lib/global_flow.ml b/compiler/lib/global_flow.ml index 26b4f45d3..12c5caaee 100644 --- a/compiler/lib/global_flow.ml +++ b/compiler/lib/global_flow.ml @@ -230,7 +230,7 @@ let expr_deps blocks st x e = | Closure (l, cont) -> List.iter l ~f:(fun x -> add_param_def st x); cont_deps blocks st cont - | Field (y, _) -> add_dep st x y + | Field (y, _, _) -> add_dep st x y let program_deps st { blocks; _ } = Addr.Map.iter @@ -241,7 +241,7 @@ let program_deps st { blocks; _ } = add_expr_def st x e; expr_deps blocks st x e | Assign (x, y) -> add_assign_def st x y - | Set_field (x, _, y) | Array_set (x, _, y) -> + | Set_field (x, _, _, y) | Array_set (x, _, y) -> possibly_mutable st x; do_escape st Escape y | Offset_ref _ -> ()); @@ -274,7 +274,7 @@ let program_deps st { blocks; _ } = List.iter ~f:(fun (i, _) -> match i with - | Let (y, Field (x', _)) when Var.equal b x' -> + | Let (y, Field (x', _, _)) when Var.equal b x' -> Hashtbl.add st.known_cases y tags | _ -> ()) block.body) @@ -401,7 +401,7 @@ let propagate st ~update approx x = (* A constant cannot contain a function *) Domain.bot | Closure _ | Block _ -> Domain.singleton x - | Field (y, n) -> ( + | Field (y, n, _) -> ( match Var.Tbl.get approx y with | Values { known; others } -> let tags = diff --git a/compiler/lib/parse_bytecode.ml b/compiler/lib/parse_bytecode.ml index 906895a53..9f5c4fa43 100644 --- a/compiler/lib/parse_bytecode.ml +++ b/compiler/lib/parse_bytecode.ml @@ -1313,7 +1313,7 @@ and compile infos pc state instrs = let j = getu code (pc + 2) in let y, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %a[%d]@." Var.print y Var.print x j; - compile infos (pc + 3) state ((Let (y, Field (x, j)), loc) :: instrs) + compile infos (pc + 3) state ((Let (y, Field (x, j, Non_float)), loc) :: instrs) | PUSHGETGLOBALFIELD -> let state = State.push state loc in @@ -1322,7 +1322,7 @@ and compile infos pc state instrs = let j = getu code (pc + 2) in let y, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %a[%d]@." Var.print y Var.print x j; - compile infos (pc + 3) state ((Let (y, Field (x, j)), loc) :: instrs) + compile infos (pc + 3) state ((Let (y, Field (x, j, Non_float)), loc) :: instrs) | SETGLOBAL -> let i = getu code (pc + 1) in State.size_globals state (i + 1); @@ -1488,49 +1488,40 @@ and compile infos pc state instrs = let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %a[0]@." Var.print x Var.print y; - compile infos (pc + 1) state ((Let (x, Field (y, 0)), loc) :: instrs) + compile infos (pc + 1) state ((Let (x, Field (y, 0, Non_float)), loc) :: instrs) | GETFIELD1 -> let y, _ = State.accu state in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %a[1]@." Var.print x Var.print y; - compile infos (pc + 1) state ((Let (x, Field (y, 1)), loc) :: instrs) + compile infos (pc + 1) state ((Let (x, Field (y, 1, Non_float)), loc) :: instrs) | GETFIELD2 -> let y, _ = State.accu state in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %a[2]@." Var.print x Var.print y; - compile infos (pc + 1) state ((Let (x, Field (y, 2)), loc) :: instrs) + compile infos (pc + 1) state ((Let (x, Field (y, 2, Non_float)), loc) :: instrs) | GETFIELD3 -> let y, _ = State.accu state in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %a[3]@." Var.print x Var.print y; - compile infos (pc + 1) state ((Let (x, Field (y, 3)), loc) :: instrs) + compile infos (pc + 1) state ((Let (x, Field (y, 3, Non_float)), loc) :: instrs) | GETFIELD -> let y, _ = State.accu state in let n = getu code (pc + 1) in let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = %a[%d]@." Var.print x Var.print y n; - compile infos (pc + 2) state ((Let (x, Field (y, n)), loc) :: instrs) + compile infos (pc + 2) state ((Let (x, Field (y, n, Non_float)), loc) :: instrs) | GETFLOATFIELD -> let y, _ = State.accu state in let n = getu code (pc + 1) in let x, state = State.fresh_var state loc in - if debug_parser () then Format.printf "%a = %a[%d]@." Var.print x Var.print y n; - compile - infos - (pc + 2) - state - (( Let - ( x - , Prim - ( Extern "caml_floatarray_unsafe_get" - , [ Pv y; Pc (Int (Int32.of_int n)) ] ) ) - , loc ) - :: instrs) + if debug_parser () + then Format.printf "%a = FLOAT{%a[%d]}@." Var.print x Var.print y n; + compile infos (pc + 2) state ((Let (x, Field (y, n, Float)), loc) :: instrs) | SETFIELD0 -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1542,7 +1533,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 0, z), loc) :: instrs) + ((Let (x, const 0l), loc) :: (Set_field (y, 0, Non_float, z), loc) :: instrs) | SETFIELD1 -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1554,7 +1545,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 1, z), loc) :: instrs) + ((Let (x, const 0l), loc) :: (Set_field (y, 1, Non_float, z), loc) :: instrs) | SETFIELD2 -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1566,7 +1557,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 2, z), loc) :: instrs) + ((Let (x, const 0l), loc) :: (Set_field (y, 2, Non_float, z), loc) :: instrs) | SETFIELD3 -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1578,7 +1569,7 @@ and compile infos pc state instrs = infos (pc + 1) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, 3, z), loc) :: instrs) + ((Let (x, const 0l), loc) :: (Set_field (y, 3, Non_float, z), loc) :: instrs) | SETFIELD -> let y, _ = State.accu state in let z, _ = State.peek 0 state in @@ -1591,26 +1582,21 @@ and compile infos pc state instrs = infos (pc + 2) (State.pop 1 state) - ((Let (x, const 0l), loc) :: (Set_field (y, n, z), loc) :: instrs) + ((Let (x, const 0l), loc) :: (Set_field (y, n, Non_float, z), loc) :: instrs) | SETFLOATFIELD -> let y, _ = State.accu state in let z, _ = State.peek 0 state in let n = getu code (pc + 1) in - if debug_parser () then Format.printf "%a[%d] = %a@." Var.print y n Var.print z; + if debug_parser () + then Format.printf "FLOAT{%a[%d]} = %a@." Var.print y n Var.print z; let x, state = State.fresh_var state loc in if debug_parser () then Format.printf "%a = 0@." Var.print x; compile infos (pc + 2) (State.pop 1 state) - (( Let - ( x - , Prim - ( Extern "caml_floatarray_unsafe_set" - , [ Pv y; Pc (Int (Int32.of_int n)); Pv z ] ) ) - , loc ) - :: instrs) + ((Let (x, const 0l), 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 @@ -2418,7 +2404,7 @@ and compile infos pc state instrs = (pc + 1) state ((Let (m, Prim (Array_get, [ Pv meths; Pv lab ])), loc) - :: (Let (meths, Field (obj, 0)), loc) + :: (Let (meths, Field (obj, 0, Non_float)), loc) :: instrs) | STOP -> instrs, (Stop, loc), state | RESUME -> @@ -2847,7 +2833,7 @@ let from_bytes ~prims ~debug (code : bytecode) = | None -> () | Some name -> Code.Var.name x name); need_gdata := true; - (Let (x, Field (gdata, i)), noloc) :: l + (Let (x, Field (gdata, i, Non_float)), noloc) :: l | _ -> l) in let body = diff --git a/compiler/lib/phisimpl.ml b/compiler/lib/phisimpl.ml index 159c8570a..88e541e69 100644 --- a/compiler/lib/phisimpl.ml +++ b/compiler/lib/phisimpl.ml @@ -53,7 +53,7 @@ let expr_deps blocks vars deps defs x e = | Constant _ | Apply _ | Prim _ | Special _ -> () | Closure (_, cont) -> cont_deps blocks vars deps defs cont | Block (_, a, _, _) -> Array.iter a ~f:(fun y -> add_dep deps x y) - | Field (y, _) -> add_dep deps x y + | Field (y, _, _) -> add_dep deps x y let program_deps { blocks; _ } = let nv = Var.count () in diff --git a/compiler/lib/subst.ml b/compiler/lib/subst.ml index 4e735576c..bd1e41f41 100644 --- a/compiler/lib/subst.ml +++ b/compiler/lib/subst.ml @@ -29,7 +29,7 @@ let expr s e = | Apply { f; args; exact } -> Apply { f = s f; args = List.map args ~f:(fun x -> s x); exact } | Block (n, a, k, mut) -> Block (n, Array.map a ~f:(fun x -> s x), k, mut) - | Field (x, n) -> Field (s x, n) + | Field (x, n, typ) -> Field (s x, n, typ) | Closure (l, pc) -> Closure (l, subst_cont s pc) | Special _ -> e | Prim (p, l) -> @@ -44,7 +44,7 @@ let instr s i = match i with | Let (x, e) -> Let (x, expr s e) | Assign (x, y) -> Assign (x, s y) (* x is handled like a parameter *) - | Set_field (x, n, y) -> Set_field (s x, n, s y) + | Set_field (x, n, typ, y) -> Set_field (s x, n, typ, s y) | Offset_ref (x, n) -> Offset_ref (s x, n) | Array_set (x, y, z) -> Array_set (s x, s y, s z)