summaryrefslogtreecommitdiff
path: root/asmcomp/closure.ml
diff options
context:
space:
mode:
Diffstat (limited to 'asmcomp/closure.ml')
-rw-r--r--asmcomp/closure.ml366
1 files changed, 258 insertions, 108 deletions
diff --git a/asmcomp/closure.ml b/asmcomp/closure.ml
index eff35ce4f2..2f37e0fcc7 100644
--- a/asmcomp/closure.ml
+++ b/asmcomp/closure.ml
@@ -245,14 +245,15 @@ let rec is_pure_clambda = function
| Uprim(p, args, _) -> List.for_all is_pure_clambda args
| _ -> false
-(* Simplify primitive operations on integers *)
+(* Simplify primitive operations on known arguments *)
let make_const c = (Uconst c, Value_const c)
-
+let make_const_ref c =
+ make_const(Uconst_ref(Compilenv.new_structured_constant ~shared:true c, c))
let make_const_int n = make_const (Uconst_int n)
let make_const_ptr n = make_const (Uconst_ptr n)
let make_const_bool b = make_const_ptr(if b then 1 else 0)
-let make_comparison cmp (x: int) (y: int) =
+let make_comparison cmp x y =
make_const_bool
(match cmp with
Ceq -> x = y
@@ -261,71 +262,187 @@ let make_comparison cmp (x: int) (y: int) =
| Cgt -> x > y
| Cle -> x <= y
| Cge -> x >= y)
+let make_const_float n = make_const_ref (Uconst_float n)
+let make_const_natint n = make_const_ref (Uconst_nativeint n)
+let make_const_int32 n = make_const_ref (Uconst_int32 n)
+let make_const_int64 n = make_const_ref (Uconst_int64 n)
+
+(* The [fpc] parameter is true if constant propagation of
+ floating-point computations is allowed *)
-let simplif_int_prim_pure p (args, approxs) dbg =
+let simplif_arith_prim_pure fpc p (args, approxs) dbg =
+ let default = (Uprim(p, args, dbg), Value_unknown) in
match approxs with
- [Value_const (Uconst_int x)] ->
+ (* int (or enumerated type) *)
+ | [ Value_const(Uconst_int n1 | Uconst_ptr n1) ] ->
begin match p with
- Pidentity -> make_const_int x
- | Pnegint -> make_const_int (-x)
- | Pbswap16 ->
- make_const_int (((x land 0xff) lsl 8) lor
- ((x land 0xff00) lsr 8))
- | Poffsetint y -> make_const_int (x + y)
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Pnot -> make_const_bool (n1 = 0)
+ | Pnegint -> make_const_int (- n1)
+ | Poffsetint n -> make_const_int (n + n1)
+ | Pfloatofint when fpc -> make_const_float (float_of_int n1)
+ | Pbintofint Pnativeint -> make_const_natint (Nativeint.of_int n1)
+ | Pbintofint Pint32 -> make_const_int32 (Int32.of_int n1)
+ | Pbintofint Pint64 -> make_const_int64 (Int64.of_int n1)
+ | Pbswap16 -> make_const_int (((n1 land 0xff) lsl 8)
+ lor ((n1 land 0xff00) lsr 8))
+ | _ -> default
end
- | [Value_const (Uconst_int x); Value_const (Uconst_int y)] ->
+ (* int (or enumerated type), int (or enumerated type) *)
+ | [ Value_const(Uconst_int n1 | Uconst_ptr n1);
+ Value_const(Uconst_int n2 | Uconst_ptr n2) ] ->
begin match p with
- Paddint -> make_const_int(x + y)
- | Psubint -> make_const_int(x - y)
- | Pmulint -> make_const_int(x * y)
- | Pdivint when y <> 0 -> make_const_int(x / y)
- | Pmodint when y <> 0 -> make_const_int(x mod y)
- | Pandint -> make_const_int(x land y)
- | Porint -> make_const_int(x lor y)
- | Pxorint -> make_const_int(x lxor y)
- | Plslint -> make_const_int(x lsl y)
- | Plsrint -> make_const_int(x lsr y)
- | Pasrint -> make_const_int(x asr y)
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Psequand -> make_const_bool (n1 <> 0 && n2 <> 0)
+ | Psequor -> make_const_bool (n1 <> 0 || n2 <> 0)
+ | Paddint -> make_const_int (n1 + n2)
+ | Psubint -> make_const_int (n1 - n2)
+ | Pmulint -> make_const_int (n1 * n2)
+ | Pdivint when n2 <> 0 -> make_const_int (n1 / n2)
+ | Pmodint when n2 <> 0 -> make_const_int (n1 mod n2)
+ | Pandint -> make_const_int (n1 land n2)
+ | Porint -> make_const_int (n1 lor n2)
+ | Pxorint -> make_const_int (n1 lxor n2)
+ | Plslint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_int (n1 lsl n2)
+ | Plsrint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_int (n1 lsr n2)
+ | Pasrint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_int (n1 asr n2)
+ | Pintcomp c -> make_comparison c n1 n2
+ | _ -> default
end
- | [Value_const (Uconst_ptr x)] ->
+ (* float *)
+ | [Value_const(Uconst_ref(_, Uconst_float n1))] when fpc ->
begin match p with
- Pidentity -> make_const_ptr x
- | Pnot -> make_const_bool(x = 0)
- | Pisint -> make_const_bool true
- | Pctconst c ->
- begin
- match c with
- | Big_endian -> make_const_bool Arch.big_endian
- | Word_size -> make_const_int (8*Arch.size_int)
- | Ostype_unix -> make_const_bool (Sys.os_type = "Unix")
- | Ostype_win32 -> make_const_bool (Sys.os_type = "Win32")
- | Ostype_cygwin -> make_const_bool (Sys.os_type = "Cygwin")
- end
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Pintoffloat -> make_const_int (int_of_float n1)
+ | Pnegfloat -> make_const_float (-. n1)
+ | Pabsfloat -> make_const_float (abs_float n1)
+ | _ -> default
end
- | [Value_const (Uconst_ptr x); Value_const (Uconst_ptr y)] ->
+ (* float, float *)
+ | [Value_const(Uconst_ref(_, Uconst_float n1));
+ Value_const(Uconst_ref(_, Uconst_float n2))] when fpc ->
begin match p with
- Psequand -> make_const_bool(x <> 0 && y <> 0)
- | Psequor -> make_const_bool(x <> 0 || y <> 0)
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Paddfloat -> make_const_float (n1 +. n2)
+ | Psubfloat -> make_const_float (n1 -. n2)
+ | Pmulfloat -> make_const_float (n1 *. n2)
+ | Pdivfloat -> make_const_float (n1 /. n2)
+ | Pfloatcomp c -> make_comparison c n1 n2
+ | _ -> default
end
- | [Value_const (Uconst_ptr x); Value_const (Uconst_int y)] ->
+ (* nativeint *)
+ | [Value_const(Uconst_ref(_, Uconst_nativeint n))] ->
begin match p with
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Pintofbint Pnativeint -> make_const_int (Nativeint.to_int n)
+ | Pcvtbint(Pnativeint, Pint32) -> make_const_int32 (Nativeint.to_int32 n)
+ | Pcvtbint(Pnativeint, Pint64) -> make_const_int64 (Int64.of_nativeint n)
+ | Pnegbint Pnativeint -> make_const_natint (Nativeint.neg n)
+ | _ -> default
end
- | [Value_const (Uconst_int x); Value_const (Uconst_ptr y)] ->
+ (* nativeint, nativeint *)
+ | [Value_const(Uconst_ref(_, Uconst_nativeint n1));
+ Value_const(Uconst_ref(_, Uconst_nativeint n2))] ->
begin match p with
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Paddbint Pnativeint -> make_const_natint (Nativeint.add n1 n2)
+ | Psubbint Pnativeint -> make_const_natint (Nativeint.sub n1 n2)
+ | Pmulbint Pnativeint -> make_const_natint (Nativeint.mul n1 n2)
+ | Pdivbint Pnativeint when n2 <> 0n ->
+ make_const_natint (Nativeint.div n1 n2)
+ | Pmodbint Pnativeint when n2 <> 0n ->
+ make_const_natint (Nativeint.rem n1 n2)
+ | Pandbint Pnativeint -> make_const_natint (Nativeint.logand n1 n2)
+ | Porbint Pnativeint -> make_const_natint (Nativeint.logor n1 n2)
+ | Pxorbint Pnativeint -> make_const_natint (Nativeint.logxor n1 n2)
+ | Pbintcomp(Pnativeint, c) -> make_comparison c n1 n2
+ | _ -> default
+ end
+ (* nativeint, int *)
+ | [Value_const(Uconst_ref(_, Uconst_nativeint n1));
+ Value_const(Uconst_int n2)] ->
+ begin match p with
+ | Plslbint Pnativeint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_natint (Nativeint.shift_left n1 n2)
+ | Plsrbint Pnativeint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_natint (Nativeint.shift_right_logical n1 n2)
+ | Pasrbint Pnativeint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_natint (Nativeint.shift_right n1 n2)
+ | _ -> default
+ end
+ (* int32 *)
+ | [Value_const(Uconst_ref(_, Uconst_int32 n))] ->
+ begin match p with
+ | Pintofbint Pint32 -> make_const_int (Int32.to_int n)
+ | Pcvtbint(Pint32, Pnativeint) -> make_const_natint (Nativeint.of_int32 n)
+ | Pcvtbint(Pint32, Pint64) -> make_const_int64 (Int64.of_int32 n)
+ | Pnegbint Pint32 -> make_const_int32 (Int32.neg n)
+ | _ -> default
+ end
+ (* int32, int32 *)
+ | [Value_const(Uconst_ref(_, Uconst_int32 n1));
+ Value_const(Uconst_ref(_, Uconst_int32 n2))] ->
+ begin match p with
+ | Paddbint Pint32 -> make_const_int32 (Int32.add n1 n2)
+ | Psubbint Pint32 -> make_const_int32 (Int32.sub n1 n2)
+ | Pmulbint Pint32 -> make_const_int32 (Int32.mul n1 n2)
+ | Pdivbint Pint32 when n2 <> 0l -> make_const_int32 (Int32.div n1 n2)
+ | Pmodbint Pint32 when n2 <> 0l -> make_const_int32 (Int32.rem n1 n2)
+ | Pandbint Pint32 -> make_const_int32 (Int32.logand n1 n2)
+ | Porbint Pint32 -> make_const_int32 (Int32.logor n1 n2)
+ | Pxorbint Pint32 -> make_const_int32 (Int32.logxor n1 n2)
+ | Pbintcomp(Pint32, c) -> make_comparison c n1 n2
+ | _ -> default
+ end
+ (* int32, int *)
+ | [Value_const(Uconst_ref(_, Uconst_int32 n1));
+ Value_const(Uconst_int n2)] ->
+ begin match p with
+ | Plslbint Pint32 when 0 <= n2 && n2 < 32 ->
+ make_const_int32 (Int32.shift_left n1 n2)
+ | Plsrbint Pint32 when 0 <= n2 && n2 < 32 ->
+ make_const_int32 (Int32.shift_right_logical n1 n2)
+ | Pasrbint Pint32 when 0 <= n2 && n2 < 32 ->
+ make_const_int32 (Int32.shift_right n1 n2)
+ | _ -> default
+ end
+ (* int64 *)
+ | [Value_const(Uconst_ref(_, Uconst_int64 n))] ->
+ begin match p with
+ | Pintofbint Pint64 -> make_const_int (Int64.to_int n)
+ | Pcvtbint(Pint64, Pint32) -> make_const_int32 (Int64.to_int32 n)
+ | Pcvtbint(Pint64, Pnativeint) -> make_const_natint (Int64.to_nativeint n)
+ | Pnegbint Pint64 -> make_const_int64 (Int64.neg n)
+ | _ -> default
+ end
+ (* int64, int64 *)
+ | [Value_const(Uconst_ref(_, Uconst_int64 n1));
+ Value_const(Uconst_ref(_, Uconst_int64 n2))] ->
+ begin match p with
+ | Paddbint Pint64 -> make_const_int64 (Int64.add n1 n2)
+ | Psubbint Pint64 -> make_const_int64 (Int64.sub n1 n2)
+ | Pmulbint Pint64 -> make_const_int64 (Int64.mul n1 n2)
+ | Pdivbint Pint64 when n2 <> 0L -> make_const_int64 (Int64.div n1 n2)
+ | Pmodbint Pint64 when n2 <> 0L -> make_const_int64 (Int64.rem n1 n2)
+ | Pandbint Pint64 -> make_const_int64 (Int64.logand n1 n2)
+ | Porbint Pint64 -> make_const_int64 (Int64.logor n1 n2)
+ | Pxorbint Pint64 -> make_const_int64 (Int64.logxor n1 n2)
+ | Pbintcomp(Pint64, c) -> make_comparison c n1 n2
+ | _ -> default
+ end
+ (* int64, int *)
+ | [Value_const(Uconst_ref(_, Uconst_int64 n1));
+ Value_const(Uconst_int n2)] ->
+ begin match p with
+ | Plslbint Pint64 when 0 <= n2 && n2 < 64 ->
+ make_const_int64 (Int64.shift_left n1 n2)
+ | Plsrbint Pint64 when 0 <= n2 && n2 < 64 ->
+ make_const_int64 (Int64.shift_right_logical n1 n2)
+ | Pasrbint Pint64 when 0 <= n2 && n2 < 64 ->
+ make_const_int64 (Int64.shift_right n1 n2)
+ | _ -> default
end
+ (* TODO: Pbbswap *)
+ (* Catch-all *)
| _ ->
- (Uprim(p, args, dbg), Value_unknown)
-
+ default
let field_approx n = function
| Value_tuple a when n < Array.length a -> a.(n)
@@ -333,8 +450,9 @@ let field_approx n = function
Value_const (List.nth l n)
| _ -> Value_unknown
-let simplif_prim_pure p (args, approxs) dbg =
+let simplif_prim_pure fpc p (args, approxs) dbg =
match p, args, approxs with
+ (* Block construction *)
| Pmakeblock(tag, Immutable), _, _ ->
let field = function
| Value_const c -> c
@@ -349,24 +467,43 @@ let simplif_prim_pure p (args, approxs) dbg =
with Exit ->
(Uprim(p, args, dbg), Value_tuple (Array.of_list approxs))
end
+ (* Field access *)
| Pfield n, _, [ Value_const(Uconst_ref(_, Uconst_block(_, l))) ]
when n < List.length l ->
make_const (List.nth l n)
-
- | Pfield n, [ Uprim(Pmakeblock _, ul, _) ], [approx] ->
- assert(n < List.length ul);
- List.nth ul n, field_approx n approx
-
- | Pstringlength, _, [ Value_const(Uconst_ref(_, Uconst_string s)) ]
- ->
+ | Pfield n, [ Uprim(Pmakeblock _, ul, _) ], [approx]
+ when n < List.length ul ->
+ (List.nth ul n, field_approx n approx)
+ (* Strings *)
+ | Pstringlength, _, [ Value_const(Uconst_ref(_, Uconst_string s)) ] ->
make_const_int (String.length s)
-
+ (* Identity *)
+ | Pidentity, [arg1], [app1] ->
+ (arg1, app1)
+ (* Kind test *)
+ | Pisint, _, [a1] ->
+ begin match a1 with
+ | Value_const(Uconst_int _ | Uconst_ptr _) -> make_const_bool true
+ | Value_const(Uconst_ref _) -> make_const_bool false
+ | Value_closure _ | Value_tuple _ -> make_const_bool false
+ | _ -> (Uprim(p, args, dbg), Value_unknown)
+ end
+ (* Compile-time constants *)
+ | Pctconst c, _, _ ->
+ begin match c with
+ | Big_endian -> make_const_bool Arch.big_endian
+ | Word_size -> make_const_int (8*Arch.size_int)
+ | Ostype_unix -> make_const_bool (Sys.os_type = "Unix")
+ | Ostype_win32 -> make_const_bool (Sys.os_type = "Win32")
+ | Ostype_cygwin -> make_const_bool (Sys.os_type = "Cygwin")
+ end
+ (* Catch-all *)
| _ ->
- simplif_int_prim_pure p (args, approxs) dbg
+ simplif_arith_prim_pure fpc p (args, approxs) dbg
-let simplif_prim p (args, approxs as args_approxs) dbg =
+let simplif_prim fpc p (args, approxs as args_approxs) dbg =
if List.for_all is_pure_clambda args
- then simplif_prim_pure p args_approxs dbg
+ then simplif_prim_pure fpc p args_approxs dbg
else
(* XXX : always return the same approxs as simplif_prim_pure? *)
let approx =
@@ -391,15 +528,16 @@ let approx_ulam = function
Uconst c -> Value_const c
| _ -> Value_unknown
-let rec substitute sb ulam =
+let rec substitute fpc sb ulam =
match ulam with
Uvar v ->
begin try Tbl.find v sb with Not_found -> ulam end
| Uconst _ -> ulam
| Udirect_apply(lbl, args, dbg) ->
- Udirect_apply(lbl, List.map (substitute sb) args, dbg)
+ Udirect_apply(lbl, List.map (substitute fpc sb) args, dbg)
| Ugeneric_apply(fn, args, dbg) ->
- Ugeneric_apply(substitute sb fn, List.map (substitute sb) args, dbg)
+ Ugeneric_apply(substitute fpc sb fn,
+ List.map (substitute fpc sb) args, dbg)
| Uclosure(defs, env) ->
(* Question: should we rename function labels as well? Otherwise,
there is a risk that function labels are not globally unique.
@@ -409,11 +547,12 @@ let rec substitute sb ulam =
- When we substitute offsets for idents bound by let rec
in [close], case [Lletrec], we discard the original
let rec body and use only the substituted term. *)
- Uclosure(defs, List.map (substitute sb) env)
- | Uoffset(u, ofs) -> Uoffset(substitute sb u, ofs)
+ Uclosure(defs, List.map (substitute fpc sb) env)
+ | Uoffset(u, ofs) -> Uoffset(substitute fpc sb u, ofs)
| Ulet(id, u1, u2) ->
let id' = Ident.rename id in
- Ulet(id', substitute sb u1, substitute (Tbl.add id (Uvar id') sb) u2)
+ Ulet(id', substitute fpc sb u1,
+ substitute fpc (Tbl.add id (Uvar id') sb) u2)
| Uletrec(bindings, body) ->
let bindings1 =
List.map (fun (id, rhs) -> (id, Ident.rename id, rhs)) bindings in
@@ -422,57 +561,64 @@ let rec substitute sb ulam =
(fun (id, id', _) s -> Tbl.add id (Uvar id') s)
bindings1 sb in
Uletrec(
- List.map (fun (id, id', rhs) -> (id', substitute sb' rhs)) bindings1,
- substitute sb' body)
+ List.map
+ (fun (id, id', rhs) -> (id', substitute fpc sb' rhs))
+ bindings1,
+ substitute fpc sb' body)
| Uprim(p, args, dbg) ->
- let sargs = List.map (substitute sb) args in
- let (res, _) = simplif_prim p (sargs, List.map approx_ulam sargs) dbg in
+ let sargs =
+ List.map (substitute fpc sb) args in
+ let (res, _) =
+ simplif_prim fpc p (sargs, List.map approx_ulam sargs) dbg in
res
| Uswitch(arg, sw) ->
- Uswitch(substitute sb arg,
+ Uswitch(substitute fpc sb arg,
{ sw with
us_actions_consts =
- Array.map (substitute sb) sw.us_actions_consts;
+ Array.map (substitute fpc sb) sw.us_actions_consts;
us_actions_blocks =
- Array.map (substitute sb) sw.us_actions_blocks;
+ Array.map (substitute fpc sb) sw.us_actions_blocks;
})
| Ustringswitch(arg,sw,d) ->
Ustringswitch
- (substitute sb arg,
- List.map (fun (s,act) -> s,substitute sb act) sw,
- Misc.may_map (substitute sb) d)
+ (substitute fpc sb arg,
+ List.map (fun (s,act) -> s,substitute fpc sb act) sw,
+ Misc.may_map (substitute fpc sb) d)
| Ustaticfail (nfail, args) ->
- Ustaticfail (nfail, List.map (substitute sb) args)
+ Ustaticfail (nfail, List.map (substitute fpc sb) args)
| Ucatch(nfail, ids, u1, u2) ->
- Ucatch(nfail, ids, substitute sb u1, substitute sb u2)
+ Ucatch(nfail, ids, substitute fpc sb u1, substitute fpc sb u2)
| Utrywith(u1, id, u2) ->
let id' = Ident.rename id in
- Utrywith(substitute sb u1, id', substitute (Tbl.add id (Uvar id') sb) u2)
+ Utrywith(substitute fpc sb u1, id',
+ substitute fpc (Tbl.add id (Uvar id') sb) u2)
| Uifthenelse(u1, u2, u3) ->
- begin match substitute sb u1 with
+ begin match substitute fpc sb u1 with
Uconst (Uconst_ptr n) ->
- if n <> 0 then substitute sb u2 else substitute sb u3
+ if n <> 0 then substitute fpc sb u2 else substitute fpc sb u3
| Uprim(Pmakeblock _, _, _) ->
- substitute sb u2
+ substitute fpc sb u2
| su1 ->
- Uifthenelse(su1, substitute sb u2, substitute sb u3)
+ Uifthenelse(su1, substitute fpc sb u2, substitute fpc sb u3)
end
- | Usequence(u1, u2) -> Usequence(substitute sb u1, substitute sb u2)
- | Uwhile(u1, u2) -> Uwhile(substitute sb u1, substitute sb u2)
+ | Usequence(u1, u2) ->
+ Usequence(substitute fpc sb u1, substitute fpc sb u2)
+ | Uwhile(u1, u2) ->
+ Uwhile(substitute fpc sb u1, substitute fpc sb u2)
| Ufor(id, u1, u2, dir, u3) ->
let id' = Ident.rename id in
- Ufor(id', substitute sb u1, substitute sb u2, dir,
- substitute (Tbl.add id (Uvar id') sb) u3)
+ Ufor(id', substitute fpc sb u1, substitute fpc sb u2, dir,
+ substitute fpc (Tbl.add id (Uvar id') sb) u3)
| Uassign(id, u) ->
let id' =
try
match Tbl.find id sb with Uvar i -> i | _ -> assert false
with Not_found ->
id in
- Uassign(id', substitute sb u)
+ Uassign(id', substitute fpc sb u)
| Usend(k, u1, u2, ul, dbg) ->
- Usend(k, substitute sb u1, substitute sb u2, List.map (substitute sb) ul,
- dbg)
+ Usend(k, substitute fpc sb u1, substitute fpc sb u2,
+ List.map (substitute fpc sb) ul, dbg)
(* Perform an inline expansion *)
@@ -484,12 +630,12 @@ let no_effects = function
| Uclosure _ -> true
| u -> is_simple_argument u
-let rec bind_params_rec subst params args body =
+let rec bind_params_rec fpc subst params args body =
match (params, args) with
- ([], []) -> substitute subst body
+ ([], []) -> substitute fpc subst body
| (p1 :: pl, a1 :: al) ->
if is_simple_argument a1 then
- bind_params_rec (Tbl.add p1 a1 subst) pl al body
+ bind_params_rec fpc (Tbl.add p1 a1 subst) pl al body
else begin
let p1' = Ident.rename p1 in
let u1, u2 =
@@ -500,17 +646,17 @@ let rec bind_params_rec subst params args body =
a1, Uvar p1'
in
let body' =
- bind_params_rec (Tbl.add p1 u2 subst) pl al body in
+ bind_params_rec fpc (Tbl.add p1 u2 subst) pl al body in
if occurs_var p1 body then Ulet(p1', u1, body')
else if no_effects a1 then body'
else Usequence(a1, body')
end
| (_, _) -> assert false
-let bind_params params args body =
+let bind_params fpc params args body =
(* Reverse parameters and arguments to preserve right-to-left
evaluation order (PR#2910). *)
- bind_params_rec Tbl.empty (List.rev params) (List.rev args) body
+ bind_params_rec fpc Tbl.empty (List.rev params) (List.rev args) body
(* Check if a lambda term is ``pure'',
that is without side-effects *and* not containing function definitions *)
@@ -532,8 +678,10 @@ let direct_apply fundesc funct ufunct uargs =
if fundesc.fun_closed then uargs else uargs @ [ufunct] in
let app =
match fundesc.fun_inline with
- None -> Udirect_apply(fundesc.fun_label, app_args, Debuginfo.none)
- | Some(params, body) -> bind_params params app_args body in
+ | None ->
+ Udirect_apply(fundesc.fun_label, app_args, Debuginfo.none)
+ | Some(params, body) ->
+ bind_params fundesc.fun_float_const_prop params app_args body in
(* If ufunct can contain side-effects or function definitions,
we must make sure that it is evaluated exactly once.
If the function is not closed, we evaluate ufunct as part of the
@@ -648,14 +796,14 @@ let rec close fenv cenv = function
str (Uconst_block (tag, List.map transl fields))
| Const_float_array sl ->
(* constant float arrays are really immutable *)
- str (Uconst_float_array sl)
+ str (Uconst_float_array (List.map float_of_string sl))
| Const_immstring s ->
str (Uconst_string s)
| Const_base (Const_string (s, _)) ->
(* strings (even literal ones) are mutable! *)
(* of course, the empty string is really immutable *)
str ~shared:false(*(String.length s = 0)*) (Uconst_string s)
- | Const_base(Const_float x) -> str (Uconst_float x)
+ | Const_base(Const_float x) -> str (Uconst_float (float_of_string x))
| Const_base(Const_int32 x) -> str (Uconst_int32 x)
| Const_base(Const_int64 x) -> str (Uconst_int64 x)
| Const_base(Const_nativeint x) -> str (Uconst_nativeint x)
@@ -749,7 +897,7 @@ let rec close fenv cenv = function
(fun (id, pos, approx) sb ->
Tbl.add id (Uoffset(Uvar clos_ident, pos)) sb)
infos Tbl.empty in
- (Ulet(clos_ident, clos, substitute sb ubody),
+ (Ulet(clos_ident, clos, substitute !Clflags.float_const_prop sb ubody),
approx)
end else begin
(* General case: recursive definition of values *)
@@ -785,7 +933,8 @@ let rec close fenv cenv = function
(Uprim(Praise k, [ulam], Debuginfo.from_raise ev),
Value_unknown)
| Lprim(p, args) ->
- simplif_prim p (close_list_approx fenv cenv args) Debuginfo.none
+ simplif_prim !Clflags.float_const_prop
+ p (close_list_approx fenv cenv args) Debuginfo.none
| Lswitch(arg, sw) ->
let fn fail =
let (uarg, _) = close fenv cenv arg in
@@ -925,7 +1074,8 @@ and close_functions fenv cenv fun_defs =
{fun_label = label;
fun_arity = (if kind = Tupled then -arity else arity);
fun_closed = initially_closed;
- fun_inline = None } in
+ fun_inline = None;
+ fun_float_const_prop = !Clflags.float_const_prop } in
(id, params, body, fundesc)
| (_, _) -> fatal_error "Closure.close_functions")
fun_defs in