@@ -50,14 +50,6 @@ let rec split_list n l =
50
50
| a ::l -> let (l1, l2) = split_list (n-1 ) l in (a::l1, l2)
51
51
end
52
52
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
-
61
53
(* Auxiliary for accessing globals. We change the name of the global
62
54
to the name of the corresponding asm symbol. This is done here
63
55
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 =
703
695
| Uunreachable ->
704
696
Uunreachable
705
697
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
+
706
710
type env = {
707
711
backend : (module Backend_intf .S );
708
- cenv : ulambda V.Map .t ;
712
+ cenv : closure_env ;
709
713
fenv : value_approximation V.Map .t ;
710
714
mutable_vars : V.Set .t ;
711
715
}
@@ -884,8 +888,19 @@ let close_approx_var { fenv; cenv } id =
884
888
match approx with
885
889
Value_const c -> make_const c
886
890
| 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)
889
904
890
905
let close_var env id =
891
906
let (ulam, _app) = close_approx_var env id in ulam
@@ -1292,16 +1307,29 @@ and close_functions { backend; fenv; cenv; mutable_vars } fun_defs =
1292
1307
(* This reference will be set to false if the hypothesis that a function
1293
1308
does not use its environment parameter is invalidated. *)
1294
1309
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
1295
1323
(* Translate each function definition *)
1296
1324
let clos_fundef (id , params , return , body , fundesc , dbg ) env_pos =
1297
1325
let env_param = V. create_local " env" in
1298
- let cenv_fv =
1299
- build_closure_env env_param (fv_pos - env_pos) fv in
1300
1326
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
1305
1333
let (ubody, approx) =
1306
1334
close { backend; fenv = fenv_rec; cenv = cenv_body; mutable_vars } body
1307
1335
in
@@ -1510,7 +1538,7 @@ let intro ~backend ~size lam =
1510
1538
Compilenv. set_global_approx(Value_tuple ! global_approx);
1511
1539
let (ulam, _approx) =
1512
1540
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
1514
1542
in
1515
1543
let opaque =
1516
1544
! Clflags. opaque
0 commit comments