@@ -50,14 +50,6 @@ let rec split_list n l =
5050 | a ::l -> let (l1, l2) = split_list (n-1 ) l in (a::l1, l2)
5151 end
5252
53- let rec build_closure_env env_param pos = function
54- [] -> V.Map. empty
55- | id :: rem ->
56- V.Map. add id
57- (Uprim (P. Pfield (pos, Pointer , Immutable ),
58- [Uvar env_param], Debuginfo. none))
59- (build_closure_env env_param (pos+ 1 ) rem)
60-
6153(* Auxiliary for accessing globals. We change the name of the global
6254 to the name of the corresponding asm symbol. This is done here
6355 and no longer in Cmmgen so that approximations stored in .cmx files
@@ -703,9 +695,21 @@ let rec substitute loc ((backend, fpc) as st) sb rn ulam =
703695 | Uunreachable ->
704696 Uunreachable
705697
698+ type closure_entry =
699+ | Free_variable of int
700+ | Function of int
701+
702+ type closure_env =
703+ | Not_in_closure
704+ | In_closure of {
705+ entries : closure_entry V.Map .t ;
706+ env_param : V .t ;
707+ env_pos : int ;
708+ }
709+
706710type env = {
707711 backend : (module Backend_intf .S );
708- cenv : ulambda V.Map .t ;
712+ cenv : closure_env ;
709713 fenv : value_approximation V.Map .t ;
710714 mutable_vars : V.Set .t ;
711715}
@@ -884,8 +888,19 @@ let close_approx_var { fenv; cenv } id =
884888 match approx with
885889 Value_const c -> make_const c
886890 | approx ->
887- let subst = try V.Map. find id cenv with Not_found -> Uvar id in
888- (subst, approx)
891+ match cenv with
892+ | Not_in_closure -> Uvar id, approx
893+ | In_closure { entries; env_param; env_pos } ->
894+ let subst =
895+ match V.Map. find id entries with
896+ | Free_variable fv_pos ->
897+ Uprim (P. Pfield (fv_pos - env_pos, Pointer , Immutable ),
898+ [Uvar env_param], Debuginfo. none)
899+ | Function fun_pos ->
900+ Uoffset (Uvar env_param, fun_pos - env_pos)
901+ | exception Not_found -> Uvar id
902+ in
903+ (subst, approx)
889904
890905let close_var env id =
891906 let (ulam, _app) = close_approx_var env id in ulam
@@ -1292,16 +1307,29 @@ and close_functions { backend; fenv; cenv; mutable_vars } fun_defs =
12921307 (* This reference will be set to false if the hypothesis that a function
12931308 does not use its environment parameter is invalidated. *)
12941309 let useless_env = ref initially_closed in
1310+ let cenv_entries =
1311+ let rec free_variables_entries fv_pos = function
1312+ [] -> V.Map. empty
1313+ | id :: rem ->
1314+ V.Map. add id (Free_variable fv_pos)
1315+ (free_variables_entries (fv_pos+ 1 ) rem)
1316+ in
1317+ let entries_fv = free_variables_entries fv_pos fv in
1318+ List. fold_right2
1319+ (fun (id , _params , _return , _body , _fundesc , _dbg ) pos env ->
1320+ V.Map. add id (Function pos) env)
1321+ uncurried_defs clos_offsets entries_fv
1322+ in
12951323 (* Translate each function definition *)
12961324 let clos_fundef (id , params , return , body , fundesc , dbg ) env_pos =
12971325 let env_param = V. create_local " env" in
1298- let cenv_fv =
1299- build_closure_env env_param (fv_pos - env_pos) fv in
13001326 let cenv_body =
1301- List. fold_right2
1302- (fun (id , _params , _return , _body , _fundesc , _dbg ) pos env ->
1303- V.Map. add id (Uoffset (Uvar env_param, pos - env_pos)) env)
1304- uncurried_defs clos_offsets cenv_fv in
1327+ In_closure {
1328+ entries = cenv_entries;
1329+ env_param;
1330+ env_pos;
1331+ }
1332+ in
13051333 let (ubody, approx) =
13061334 close { backend; fenv = fenv_rec; cenv = cenv_body; mutable_vars } body
13071335 in
@@ -1510,7 +1538,7 @@ let intro ~backend ~size lam =
15101538 Compilenv. set_global_approx(Value_tuple ! global_approx);
15111539 let (ulam, _approx) =
15121540 close { backend; fenv = V.Map. empty;
1513- cenv = V.Map. empty ; mutable_vars = V.Set. empty } lam
1541+ cenv = Not_in_closure ; mutable_vars = V.Set. empty } lam
15141542 in
15151543 let opaque =
15161544 ! Clflags. opaque
0 commit comments