@@ -30,13 +30,19 @@ let new_label () =
30
30
(* *** Operations on compilation environments. ****)
31
31
32
32
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 }
34
34
35
35
(* Add a stack-allocated variable *)
36
36
37
37
let add_var id pos env =
38
38
{ 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)
40
46
41
47
(* *** Examination of the continuation ****)
42
48
@@ -186,8 +192,16 @@ and sz_staticfail = ref 0
186
192
187
193
(* Function bodies that remain to be compiled *)
188
194
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)
191
205
192
206
(* Name of current compilation unit (for debugging events) *)
193
207
@@ -211,6 +225,10 @@ let rec comp_expr env exp sz cont =
211
225
try
212
226
let pos = Ident. find_same id env.ce_heap in
213
227
Kenvacc (pos) :: cont
228
+ with Not_found ->
229
+ try
230
+ let ofs = Ident. find_same id env.ce_rec in
231
+ Koffsetclosure (ofs) :: cont
214
232
with Not_found ->
215
233
Ident. print id; print_newline() ;
216
234
fatal_error " Bytegen.comp_expr: var"
@@ -252,40 +270,59 @@ let rec comp_expr env exp sz cont =
252
270
| Lfunction (kind , params , body ) -> (* assume kind = Curried *)
253
271
let lbl = new_label() in
254
272
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;
256
277
comp_args env (List. map (fun n -> Lvar n) fv) sz
257
278
(Kclosure (lbl, List. length fv) :: cont)
258
279
| Llet (str , id , arg , body ) ->
259
280
comp_expr env arg sz
260
281
(Kpush :: comp_expr (add_var id (sz+ 1 ) env) body (sz+ 1 )
261
282
(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)))
271
283
| Lletrec (decl , body ) ->
272
284
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
289
326
| Lprim (Pidentity, [arg ]) ->
290
327
comp_expr env arg sz cont
291
328
| Lprim (Pnot, [arg ]) ->
@@ -329,6 +366,19 @@ let rec comp_expr env exp sz cont =
329
366
when n > = immed_min & n < = immed_max ->
330
367
let ofs = if prim == Paddint then n else - n in
331
368
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
332
382
| Lprim (p , args ) ->
333
383
let instr =
334
384
match p with
@@ -338,8 +388,8 @@ let rec comp_expr env exp sz cont =
338
388
| Pmakeblock (tag , mut ) -> Kmakeblock (List. length args, tag)
339
389
| Pfield n -> Kgetfield n
340
390
| 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
343
393
| Pccall p -> Kccall (p.prim_name, p.prim_arity)
344
394
| Pnegint -> Knegint
345
395
| Paddint -> Kaddint
@@ -374,12 +424,19 @@ let rec comp_expr env exp sz cont =
374
424
| Pstringsets -> Kccall (" string_set" , 3 )
375
425
| Pstringrefu -> Kgetstringchar
376
426
| Pstringsetu -> Ksetstringchar
377
- | Pmakearray kind -> Kmakeblock (List. length args, 0 )
378
427
| 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
383
440
| Pbittest -> Kccall (" bitvect_test" , 2 )
384
441
| _ -> fatal_error " Bytegen.comp_expr: prim" in
385
442
comp_args env args sz (instr :: cont)
@@ -545,20 +602,21 @@ and comp_binary_test env cond ifso ifnot sz cont =
545
602
546
603
(* *** Compilation of functions ****)
547
604
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
551
608
[] -> 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
553
610
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
556
614
let cont1 =
557
- comp_expr env fun_body arity (Kreturn arity :: cont) in
615
+ comp_expr env tc.body arity (Kreturn arity :: cont) in
558
616
if arity > 1 then
559
- Krestart :: Klabel entry_lbl :: Kgrab (arity - 1 ) :: cont1
617
+ Krestart :: Klabel tc.label :: Kgrab (arity - 1 ) :: cont1
560
618
else
561
- Klabel entry_lbl :: cont1
619
+ Klabel tc.label :: cont1
562
620
563
621
let comp_remainder cont =
564
622
let c = ref cont in
0 commit comments