Skip to content

Commit ea8fe59

Browse files
committed
Adoption des memes representations que dans ocamlopt pour les tableaux de flottants et les fonctions mutuellement recursives.
Simplification de la compilation du let rec de valeurs. git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@1895 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
1 parent d83bfc2 commit ea8fe59

22 files changed

+607
-222
lines changed

Diff for: bytecomp/bytegen.ml

+104-46
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,19 @@ let new_label () =
3030
(**** Operations on compilation environments. ****)
3131

3232
let empty_env =
33-
{ ce_stack = Ident.empty; ce_heap = Ident.empty }
33+
{ ce_stack = Ident.empty; ce_heap = Ident.empty; ce_rec = Ident.empty }
3434

3535
(* Add a stack-allocated variable *)
3636

3737
let add_var id pos env =
3838
{ ce_stack = Ident.add id pos env.ce_stack;
39-
ce_heap = env.ce_heap }
39+
ce_heap = env.ce_heap;
40+
ce_rec = env.ce_rec }
41+
42+
let rec add_vars idlist pos env =
43+
match idlist with
44+
[] -> env
45+
| id :: rem -> add_vars rem (pos + 1) (add_var id pos env)
4046

4147
(**** Examination of the continuation ****)
4248

@@ -186,8 +192,16 @@ and sz_staticfail = ref 0
186192

187193
(* Function bodies that remain to be compiled *)
188194

189-
let functions_to_compile =
190-
(Stack.create () : (Ident.t list * lambda * label * Ident.t list) Stack.t)
195+
type function_to_compile =
196+
{ params: Ident.t list; (* function parameters *)
197+
body: lambda; (* the function body *)
198+
label: label; (* the label of the function entry *)
199+
free_vars: Ident.t list; (* free variables of the function *)
200+
num_defs: int; (* number of mutually recursive definitions *)
201+
rec_vars: Ident.t list; (* mutually recursive fn names *)
202+
rec_pos: int } (* rank in recursive definition *)
203+
204+
let functions_to_compile = (Stack.create () : function_to_compile Stack.t)
191205

192206
(* Name of current compilation unit (for debugging events) *)
193207

@@ -211,6 +225,10 @@ let rec comp_expr env exp sz cont =
211225
try
212226
let pos = Ident.find_same id env.ce_heap in
213227
Kenvacc(pos) :: cont
228+
with Not_found ->
229+
try
230+
let ofs = Ident.find_same id env.ce_rec in
231+
Koffsetclosure(ofs) :: cont
214232
with Not_found ->
215233
Ident.print id; print_newline();
216234
fatal_error "Bytegen.comp_expr: var"
@@ -252,40 +270,59 @@ let rec comp_expr env exp sz cont =
252270
| Lfunction(kind, params, body) -> (* assume kind = Curried *)
253271
let lbl = new_label() in
254272
let fv = IdentSet.elements(free_variables exp) in
255-
Stack.push (params, body, lbl, fv) functions_to_compile;
273+
let to_compile =
274+
{ params = params; body = body; label = lbl;
275+
free_vars = fv; num_defs = 1; rec_vars = []; rec_pos = 0 } in
276+
Stack.push to_compile functions_to_compile;
256277
comp_args env (List.map (fun n -> Lvar n) fv) sz
257278
(Kclosure(lbl, List.length fv) :: cont)
258279
| Llet(str, id, arg, body) ->
259280
comp_expr env arg sz
260281
(Kpush :: comp_expr (add_var id (sz+1) env) body (sz+1)
261282
(add_pop 1 cont))
262-
| Lletrec(([id, Lfunction(kind, params, funct_body)] as decl), let_body) ->
263-
let lbl = new_label() in
264-
let fv =
265-
IdentSet.elements (free_variables (Lletrec(decl, lambda_unit))) in
266-
Stack.push (params, funct_body, lbl, id :: fv) functions_to_compile;
267-
comp_args env (List.map (fun n -> Lvar n) fv) sz
268-
(Kclosurerec(lbl, List.length fv) :: Kpush ::
269-
(comp_expr (add_var id (sz+1) env) let_body (sz+1)
270-
(add_pop 1 cont)))
271283
| Lletrec(decl, body) ->
272284
let ndecl = List.length decl in
273-
let decl_size =
274-
List.map (fun (id, exp) -> (id, exp, size_of_lambda exp)) decl in
275-
let rec comp_decl new_env sz i = function
276-
[] ->
277-
comp_expr new_env body sz (add_pop ndecl cont)
278-
| (id, exp, blocksize) :: rem ->
279-
comp_expr new_env exp sz
280-
(Kpush :: Kacc i :: Kupdate blocksize ::
281-
comp_decl new_env sz (i-1) rem) in
282-
let rec comp_init new_env sz = function
283-
[] ->
284-
comp_decl new_env sz ndecl decl_size
285-
| (id, exp, blocksize) :: rem ->
286-
Kdummy blocksize :: Kpush ::
287-
comp_init (add_var id (sz+1) new_env) (sz+1) rem in
288-
comp_init env sz decl_size
285+
if List.for_all (function (_, Lfunction(_,_,_)) -> true | _ -> false)
286+
decl then begin
287+
(* let rec of functions *)
288+
let fv =
289+
IdentSet.elements (free_variables (Lletrec(decl, lambda_unit))) in
290+
let rec_idents = List.map (fun (id, lam) -> id) decl in
291+
let rec comp_fun pos = function
292+
[] -> []
293+
| (id, Lfunction(kind, params, body)) :: rem ->
294+
let lbl = new_label() in
295+
let to_compile =
296+
{ params = params; body = body; label = lbl; free_vars = fv;
297+
num_defs = ndecl; rec_vars = rec_idents; rec_pos = pos} in
298+
Stack.push to_compile functions_to_compile;
299+
lbl :: comp_fun (pos + 1) rem
300+
| _ -> assert false in
301+
let lbls = comp_fun 0 decl in
302+
let num_funcs = List.length lbls in
303+
comp_args env (List.map (fun n -> Lvar n) fv) sz
304+
(Kclosurerec(lbls, List.length fv) ::
305+
(comp_expr (add_vars rec_idents (sz+1) env) body (sz + ndecl)
306+
(add_pop ndecl cont)))
307+
end else begin
308+
let decl_size =
309+
List.map (fun (id, exp) -> (id, exp, size_of_lambda exp)) decl in
310+
let rec comp_decl new_env sz i = function
311+
[] ->
312+
comp_expr new_env body sz (add_pop ndecl cont)
313+
| (id, exp, blocksize) :: rem ->
314+
comp_expr new_env exp sz
315+
(Kpush :: Kacc i :: Kccall("update_dummy", 2) ::
316+
comp_decl new_env sz (i-1) rem) in
317+
let rec comp_init new_env sz = function
318+
[] ->
319+
comp_decl new_env sz ndecl decl_size
320+
| (id, exp, blocksize) :: rem ->
321+
Kconst(Const_base(Const_int blocksize)) ::
322+
Kccall("alloc_dummy", 1) :: Kpush ::
323+
comp_init (add_var id (sz+1) new_env) (sz+1) rem in
324+
comp_init env sz decl_size
325+
end
289326
| Lprim(Pidentity, [arg]) ->
290327
comp_expr env arg sz cont
291328
| Lprim(Pnot, [arg]) ->
@@ -329,6 +366,19 @@ let rec comp_expr env exp sz cont =
329366
when n >= immed_min & n <= immed_max ->
330367
let ofs = if prim == Paddint then n else -n in
331368
comp_expr env arg sz (Koffsetint ofs :: cont)
369+
| Lprim(Pmakearray kind, args) ->
370+
begin match kind with
371+
Pintarray | Paddrarray ->
372+
comp_args env args sz (Kmakeblock(List.length args, 0) :: cont)
373+
| Pfloatarray ->
374+
comp_args env args sz (Kmakefloatblock(List.length args) :: cont)
375+
| Pgenarray ->
376+
if args = []
377+
then Kmakeblock(0, 0) :: cont
378+
else comp_args env args sz
379+
(Kmakeblock(List.length args, 0) ::
380+
Kccall("make_array", 1) :: cont)
381+
end
332382
| Lprim(p, args) ->
333383
let instr =
334384
match p with
@@ -338,8 +388,8 @@ let rec comp_expr env exp sz cont =
338388
| Pmakeblock(tag, mut) -> Kmakeblock(List.length args, tag)
339389
| Pfield n -> Kgetfield n
340390
| Psetfield(n, ptr) -> Ksetfield n
341-
| Pfloatfield n -> Kgetfield n
342-
| Psetfloatfield n -> Ksetfield n
391+
| Pfloatfield n -> Kgetfloatfield n
392+
| Psetfloatfield n -> Ksetfloatfield n
343393
| Pccall p -> Kccall(p.prim_name, p.prim_arity)
344394
| Pnegint -> Knegint
345395
| Paddint -> Kaddint
@@ -374,12 +424,19 @@ let rec comp_expr env exp sz cont =
374424
| Pstringsets -> Kccall("string_set", 3)
375425
| Pstringrefu -> Kgetstringchar
376426
| Pstringsetu -> Ksetstringchar
377-
| Pmakearray kind -> Kmakeblock(List.length args, 0)
378427
| Parraylength kind -> Kvectlength
379-
| Parrayrefs kind -> Kccall("array_get", 2)
380-
| Parraysets kind -> Kccall("array_set", 3)
381-
| Parrayrefu kind -> Kgetvectitem
382-
| Parraysetu kind -> Ksetvectitem
428+
| Parrayrefs Pgenarray -> Kccall("array_get", 2)
429+
| Parrayrefs Pfloatarray -> Kccall("array_get_float", 2)
430+
| Parrayrefs _ -> Kccall("array_get_addr", 2)
431+
| Parraysets Pgenarray -> Kccall("array_set", 3)
432+
| Parraysets Pfloatarray -> Kccall("array_set_float", 3)
433+
| Parraysets _ -> Kccall("array_set_addr", 3)
434+
| Parrayrefu Pgenarray -> Kccall("array_unsafe_get", 2)
435+
| Parrayrefu Pfloatarray -> Kccall("array_unsafe_get_float", 2)
436+
| Parrayrefu _ -> Kgetvectitem
437+
| Parraysetu Pgenarray -> Kccall("array_unsafe_set", 3)
438+
| Parraysetu Pfloatarray -> Kccall("array_unsafe_set_float", 3)
439+
| Parraysetu _ -> Ksetvectitem
383440
| Pbittest -> Kccall("bitvect_test", 2)
384441
| _ -> fatal_error "Bytegen.comp_expr: prim" in
385442
comp_args env args sz (instr :: cont)
@@ -545,20 +602,21 @@ and comp_binary_test env cond ifso ifnot sz cont =
545602

546603
(**** Compilation of functions ****)
547604

548-
let comp_function (params, fun_body, entry_lbl, free_vars) cont =
549-
let arity = List.length params in
550-
let rec pos_args pos delta = function
605+
let comp_function tc cont =
606+
let arity = List.length tc.params in
607+
let rec positions pos delta = function
551608
[] -> Ident.empty
552-
| id :: rem -> Ident.add id pos (pos_args (pos+delta) delta rem) in
609+
| id :: rem -> Ident.add id pos (positions (pos + delta) delta rem) in
553610
let env =
554-
{ ce_stack = pos_args arity (-1) params;
555-
ce_heap = pos_args 0 1 free_vars } in
611+
{ ce_stack = positions arity (-1) tc.params;
612+
ce_heap = positions (2 * (tc.num_defs - tc.rec_pos) - 1) 1 tc.free_vars;
613+
ce_rec = positions (-2 * tc.rec_pos) 2 tc.rec_vars } in
556614
let cont1 =
557-
comp_expr env fun_body arity (Kreturn arity :: cont) in
615+
comp_expr env tc.body arity (Kreturn arity :: cont) in
558616
if arity > 1 then
559-
Krestart :: Klabel entry_lbl :: Kgrab(arity - 1) :: cont1
617+
Krestart :: Klabel tc.label :: Kgrab(arity - 1) :: cont1
560618
else
561-
Klabel entry_lbl :: cont1
619+
Klabel tc.label :: cont1
562620

563621
let comp_remainder cont =
564622
let c = ref cont in

Diff for: bytecomp/emitcode.ml

+24-8
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ let emit_instr = function
159159
| Kacc n ->
160160
if n < 8 then out(opACC0 + n) else (out opACC; out_int n)
161161
| Kenvacc n ->
162-
if n < 4 then out(opENVACC1 + n) else (out opENVACC; out_int (n+1))
162+
if n >= 1 && n < 4
163+
then out(opENVACC1 + n - 1)
164+
else (out opENVACC; out_int n)
163165
| Kpush ->
164166
out opPUSH
165167
| Kpop n ->
@@ -176,7 +178,14 @@ let emit_instr = function
176178
| Krestart -> out opRESTART
177179
| Kgrab n -> out opGRAB; out_int n
178180
| Kclosure(lbl, n) -> out opCLOSURE; out_int n; out_label lbl
179-
| Kclosurerec(lbl, n) -> out opCLOSUREREC; out_int n; out_label lbl
181+
| Kclosurerec(lbls, n) ->
182+
out opCLOSUREREC; out_int (List.length lbls); out_int n;
183+
let org = !out_position in
184+
List.iter (out_label_with_orig org) lbls
185+
| Koffsetclosure ofs ->
186+
if ofs = -2 || ofs = 0 || ofs = 2
187+
then out (opOFFSETCLOSURE0 + ofs / 2)
188+
else (out opOFFSETCLOSURE; out_int ofs)
180189
| Kgetglobal q -> out opGETGLOBAL; slot_for_getglobal q
181190
| Ksetglobal q -> out opSETGLOBAL; slot_for_setglobal q
182191
| Kconst sc ->
@@ -205,9 +214,10 @@ let emit_instr = function
205214
if n < 4 then out(opGETFIELD0 + n) else (out opGETFIELD; out_int n)
206215
| Ksetfield n ->
207216
if n < 4 then out(opSETFIELD0 + n) else (out opSETFIELD; out_int n)
208-
| Kdummy n ->
209-
if n = 0 then out opATOM0 else (out opDUMMY; out_int n)
210-
| Kupdate n -> out opUPDATE
217+
| Kmakefloatblock(n) ->
218+
if n = 0 then out opATOM0 else (out opMAKEFLOATBLOCK; out_int n)
219+
| Kgetfloatfield n -> out opGETFLOATFIELD; out_int n
220+
| Ksetfloatfield n -> out opSETFLOATFIELD; out_int n
211221
| Kvectlength -> out opVECTLENGTH
212222
| Kgetvectitem -> out opGETVECTITEM
213223
| Ksetvectitem -> out opSETVECTITEM
@@ -257,8 +267,14 @@ let rec emit = function
257267
if n < 8 then out(opPUSHACC0 + n) else (out opPUSHACC; out_int n);
258268
emit c
259269
| Kpush :: Kenvacc n :: c ->
260-
if n < 4 then out(opPUSHENVACC1 + n)
261-
else (out opPUSHENVACC; out_int (n+1));
270+
if n >= 1 && n < 4
271+
then out(opPUSHENVACC1 + n - 1)
272+
else (out opPUSHENVACC; out_int n);
273+
emit c
274+
| Kpush :: Koffsetclosure ofs :: c ->
275+
if ofs = -2 || ofs = 0 || ofs = 2
276+
then out(opPUSHOFFSETCLOSURE0 + ofs / 2)
277+
else (out opPUSHOFFSETCLOSURE; out_int ofs);
262278
emit c
263279
| Kpush :: Kgetglobal id :: Kgetfield n :: c ->
264280
out opPUSHGETGLOBALFIELD; slot_for_getglobal id; out_int n; emit c
@@ -286,7 +302,7 @@ let rec emit = function
286302
(Kgetglobal _ as instr1) :: (Kgetfield _ as instr2) :: c ->
287303
emit (Kpush :: instr1 :: instr2 :: ev :: c)
288304
| Kpush :: (Kevent {ev_kind = Event_before} as ev) ::
289-
(Kacc _ | Kenvacc _ | Kgetglobal _ | Kconst _ as instr) :: c ->
305+
(Kacc _ | Kenvacc _ | Koffsetclosure _ | Kgetglobal _ | Kconst _ as instr) :: c ->
290306
emit (Kpush :: instr :: ev :: c)
291307
| Kgetglobal id :: Kgetfield n :: c ->
292308
out opGETGLOBALFIELD; slot_for_getglobal id; out_int n; emit c

Diff for: bytecomp/instruct.ml

+7-5
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ open Lambda
1515

1616
type compilation_env =
1717
{ ce_stack: int Ident.tbl;
18-
ce_heap: int Ident.tbl }
19-
18+
ce_heap: int Ident.tbl;
19+
ce_rec: int Ident.tbl }
2020

2121
type debug_event =
2222
{ mutable ev_pos: int; (* Position in bytecode *)
@@ -60,15 +60,17 @@ type instruction =
6060
| Krestart
6161
| Kgrab of int (* number of arguments *)
6262
| Kclosure of label * int
63-
| Kclosurerec of label * int
63+
| Kclosurerec of label list * int
64+
| Koffsetclosure of int
6465
| Kgetglobal of Ident.t
6566
| Ksetglobal of Ident.t
6667
| Kconst of structured_constant
6768
| Kmakeblock of int * int (* size, tag *)
69+
| Kmakefloatblock of int
6870
| Kgetfield of int
6971
| Ksetfield of int
70-
| Kdummy of int
71-
| Kupdate of int
72+
| Kgetfloatfield of int
73+
| Ksetfloatfield of int
7274
| Kvectlength
7375
| Kgetvectitem
7476
| Ksetvectitem

Diff for: bytecomp/instruct.mli

+13-5
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@ open Lambda
1919

2020
type compilation_env =
2121
{ ce_stack: int Ident.tbl; (* Positions of variables in the stack *)
22-
ce_heap: int Ident.tbl } (* Structure of the heap-allocated env *)
22+
ce_heap: int Ident.tbl; (* Structure of the heap-allocated env *)
23+
ce_rec: int Ident.tbl } (* Functions bound by the same let rec *)
2324

2425
(* The ce_stack component gives locations of variables residing
2526
in the stack. The locations are offsets w.r.t. the origin of the
2627
stack frame.
2728
The ce_heap component gives the positions of variables residing in the
28-
heap-allocated environment. *)
29+
heap-allocated environment.
30+
The ce_rec component associate offsets to identifiers for functions
31+
bound by the same let rec as the current function. The offsets
32+
are used by the OFFSETCLOSURE instruction to recover the closure
33+
pointer of the desired function from the env register (which
34+
points to the closure for the current function). *)
2935

3036
(* Debugging events *)
3137

@@ -73,15 +79,17 @@ type instruction =
7379
| Krestart
7480
| Kgrab of int (* number of arguments *)
7581
| Kclosure of label * int
76-
| Kclosurerec of label * int
82+
| Kclosurerec of label list * int
83+
| Koffsetclosure of int
7784
| Kgetglobal of Ident.t
7885
| Ksetglobal of Ident.t
7986
| Kconst of structured_constant
8087
| Kmakeblock of int * int (* size, tag *)
88+
| Kmakefloatblock of int
8189
| Kgetfield of int
8290
| Ksetfield of int
83-
| Kdummy of int (* block size *)
84-
| Kupdate of int (* block size *)
91+
| Kgetfloatfield of int
92+
| Ksetfloatfield of int
8593
| Kvectlength
8694
| Kgetvectitem
8795
| Ksetvectitem

0 commit comments

Comments
 (0)