1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1996 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
13 (* $Id: cmmgen.ml 9167 2009-01-26 17:06:10Z xleroy $ *)
15 (* Translation from closed lambda to C-- *)
26 (* Local binding of complex expressions *)
28 let bind name arg fn =
30 Cvar _ | Cconst_int _ | Cconst_natint _ | Cconst_symbol _
31 | Cconst_pointer _ | Cconst_natpointer _ -> fn arg
32 | _ -> let id = Ident.create name in Clet(id, arg, fn (Cvar id))
34 let bind_nonvar name arg fn =
36 Cconst_int _ | Cconst_natint _ | Cconst_symbol _
37 | Cconst_pointer _ | Cconst_natpointer _ -> fn arg
38 | _ -> let id = Ident.create name in Clet(id, arg, fn (Cvar id))
40 (* Block headers. Meaning of the tag field: see stdlib/obj.ml *)
42 let float_tag = Cconst_int Obj.double_tag
43 let floatarray_tag = Cconst_int Obj.double_array_tag
45 let block_header tag sz =
46 Nativeint.add (Nativeint.shift_left (Nativeint.of_int sz) 10)
47 (Nativeint.of_int tag)
48 let closure_header sz = block_header Obj.closure_tag sz
49 let infix_header ofs = block_header Obj.infix_tag ofs
50 let float_header = block_header Obj.double_tag (size_float / size_addr)
51 let floatarray_header len =
52 block_header Obj.double_array_tag (len * size_float / size_addr)
53 let string_header len =
54 block_header Obj.string_tag ((len + size_addr) / size_addr)
55 let boxedint_header = block_header Obj.custom_tag 2
57 let alloc_block_header tag sz = Cconst_natint(block_header tag sz)
58 let alloc_float_header = Cconst_natint(float_header)
59 let alloc_floatarray_header len = Cconst_natint(floatarray_header len)
60 let alloc_closure_header sz = Cconst_natint(closure_header sz)
61 let alloc_infix_header ofs = Cconst_natint(infix_header ofs)
62 let alloc_boxedint_header = Cconst_natint(boxedint_header)
66 let max_repr_int = max_int asr 1
67 let min_repr_int = min_int asr 1
70 if n <= max_repr_int && n >= min_repr_int
71 then Cconst_int((n lsl 1) + 1)
73 (Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
76 if n = 0 then c else Cop(Caddi, [c; Cconst_int n])
78 let incr_int = function
79 Cconst_int n when n < max_int -> Cconst_int(n+1)
80 | Cop(Caddi, [c; Cconst_int n]) when n < max_int -> add_const c (n + 1)
83 let decr_int = function
84 Cconst_int n when n > min_int -> Cconst_int(n-1)
85 | Cop(Caddi, [c; Cconst_int n]) when n > min_int -> add_const c (n - 1)
86 | c -> add_const c (-1)
90 (Cop(Caddi, [c1; Cconst_int n1]),
91 Cop(Caddi, [c2; Cconst_int n2])) when no_overflow_add n1 n2 ->
92 add_const (Cop(Caddi, [c1; c2])) (n1 + n2)
93 | (Cop(Caddi, [c1; Cconst_int n1]), c2) ->
94 add_const (Cop(Caddi, [c1; c2])) n1
95 | (c1, Cop(Caddi, [c2; Cconst_int n2])) ->
96 add_const (Cop(Caddi, [c1; c2])) n2
97 | (Cconst_int _, _) ->
104 (Cop(Caddi, [c1; Cconst_int n1]),
105 Cop(Caddi, [c2; Cconst_int n2])) when no_overflow_sub n1 n2 ->
106 add_const (Cop(Csubi, [c1; c2])) (n1 - n2)
107 | (Cop(Caddi, [c1; Cconst_int n1]), c2) ->
108 add_const (Cop(Csubi, [c1; c2])) n1
109 | (c1, Cop(Caddi, [c2; Cconst_int n2])) when n2 <> min_int ->
110 add_const (Cop(Csubi, [c1; c2])) (-n2)
111 | (c1, Cconst_int n) when n <> min_int ->
118 (Cconst_int 0, _) -> c1
119 | (Cconst_int 1, _) -> c2
120 | (_, Cconst_int 0) -> c2
121 | (_, Cconst_int 1) -> c1
122 | (_, _) -> Cop(Cmuli, [c1; c2])
124 let tag_int = function
125 Cconst_int n -> int_const n
126 | c -> Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1])
128 let force_tag_int = function
129 Cconst_int n -> int_const n
130 | c -> Cop(Cor, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1])
132 let untag_int = function
133 Cconst_int n -> Cconst_int(n asr 1)
134 | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) -> c
135 | Cop(Cor, [Cop(Casr, [c; Cconst_int n]); Cconst_int 1])
136 when n > 0 && n < size_int * 8 ->
137 Cop(Casr, [c; Cconst_int (n+1)])
138 | Cop(Cor, [Cop(Clsr, [c; Cconst_int n]); Cconst_int 1])
139 when n > 0 && n < size_int * 8 ->
140 Cop(Clsr, [c; Cconst_int (n+1)])
141 | Cop(Cor, [c; Cconst_int 1]) -> Cop(Casr, [c; Cconst_int 1])
142 | c -> Cop(Casr, [c; Cconst_int 1])
146 (Cop(Clsl, [c; Cconst_int n1]), Cconst_int n2)
147 when n1 > 0 && n2 > 0 && n1 + n2 < size_int * 8 ->
148 Cop(Clsl, [c; Cconst_int (n1 + n2)])
152 let ignore_low_bit_int = function
153 Cop(Caddi, [(Cop(Clsl, [_; Cconst_int 1]) as c); Cconst_int 1]) -> c
154 | Cop(Cor, [c; Cconst_int 1]) -> c
157 let is_nonzero_constant = function
158 Cconst_int n -> n <> 0
159 | Cconst_natint n -> n <> 0n
162 let safe_divmod op c1 c2 dbg =
163 if !Clflags.fast || is_nonzero_constant c2 then
166 bind "divisor" c2 (fun c2 ->
170 [Cconst_symbol "caml_bucket_Division_by_zero"])))
174 let test_bool = function
175 Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) -> c
176 | Cop(Clsl, [c; Cconst_int 1]) -> c
177 | c -> Cop(Ccmpi Cne, [c; Cconst_int 1])
181 let box_float c = Cop(Calloc, [alloc_float_header; c])
183 let rec unbox_float = function
184 Cop(Calloc, [header; c]) -> c
185 | Clet(id, exp, body) -> Clet(id, exp, unbox_float body)
186 | Cifthenelse(cond, e1, e2) ->
187 Cifthenelse(cond, unbox_float e1, unbox_float e2)
188 | Csequence(e1, e2) -> Csequence(e1, unbox_float e2)
189 | Cswitch(e, tbl, el) -> Cswitch(e, tbl, Array.map unbox_float el)
190 | Ccatch(n, ids, e1, e2) -> Ccatch(n, ids, unbox_float e1, unbox_float e2)
191 | Ctrywith(e1, id, e2) -> Ctrywith(unbox_float e1, id, unbox_float e2)
192 | c -> Cop(Cload Double_u, [c])
196 let box_complex c_re c_im =
197 Cop(Calloc, [alloc_floatarray_header 2; c_re; c_im])
199 let complex_re c = Cop(Cload Double_u, [c])
200 let complex_im c = Cop(Cload Double_u,
201 [Cop(Cadda, [c; Cconst_int size_float])])
205 let return_unit c = Csequence(c, Cconst_pointer 1)
207 let rec remove_unit = function
208 Cconst_pointer 1 -> Ctuple []
209 | Csequence(c, Cconst_pointer 1) -> c
210 | Csequence(c1, c2) ->
211 Csequence(c1, remove_unit c2)
212 | Cifthenelse(cond, ifso, ifnot) ->
213 Cifthenelse(cond, remove_unit ifso, remove_unit ifnot)
214 | Cswitch(sel, index, cases) ->
215 Cswitch(sel, index, Array.map remove_unit cases)
216 | Ccatch(io, ids, body, handler) ->
217 Ccatch(io, ids, remove_unit body, remove_unit handler)
218 | Ctrywith(body, exn, handler) ->
219 Ctrywith(remove_unit body, exn, remove_unit handler)
220 | Clet(id, c1, c2) ->
221 Clet(id, c1, remove_unit c2)
222 | Cop(Capply (mty, dbg), args) ->
223 Cop(Capply (typ_void, dbg), args)
224 | Cop(Cextcall(proc, mty, alloc, dbg), args) ->
225 Cop(Cextcall(proc, typ_void, alloc, dbg), args)
226 | Cexit (_,_) as c -> c
227 | Ctuple [] as c -> c
228 | c -> Csequence(c, Ctuple [])
230 (* Access to block fields *)
232 let field_address ptr n =
235 else Cop(Cadda, [ptr; Cconst_int(n * size_addr)])
237 let get_field ptr n =
238 Cop(Cload Word, [field_address ptr n])
240 let set_field ptr n newval =
241 Cop(Cstore Word, [field_address ptr n; newval])
244 Cop(Cload Word, [Cop(Cadda, [ptr; Cconst_int(-size_int)])])
247 if big_endian then -1 else -size_int
250 if Proc.word_addressed then (* If byte loads are slow *)
251 Cop(Cand, [header ptr; Cconst_int 255])
252 else (* If byte loads are efficient *)
253 Cop(Cload Byte_unsigned,
254 [Cop(Cadda, [ptr; Cconst_int(tag_offset)])])
257 Cop(Clsr, [header ptr; Cconst_int 10])
261 let log2_size_addr = Misc.log2 size_addr
262 let log2_size_float = Misc.log2 size_float
264 let wordsize_shift = 9
265 let numfloat_shift = 9 + log2_size_float - log2_size_addr
267 let is_addr_array_hdr hdr =
268 Cop(Ccmpi Cne, [Cop(Cand, [hdr; Cconst_int 255]); floatarray_tag])
270 let is_addr_array_ptr ptr =
271 Cop(Ccmpi Cne, [get_tag ptr; floatarray_tag])
273 let addr_array_length hdr = Cop(Clsr, [hdr; Cconst_int wordsize_shift])
274 let float_array_length hdr = Cop(Clsr, [hdr; Cconst_int numfloat_shift])
277 Cop(Clsl, [c; Cconst_int n])
279 let array_indexing log2size ptr ofs =
283 if i = 0 then ptr else Cop(Cadda, [ptr; Cconst_int(i lsl log2size)])
284 | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) ->
285 Cop(Cadda, [ptr; lsl_const c log2size])
286 | Cop(Caddi, [c; Cconst_int n]) ->
287 Cop(Cadda, [Cop(Cadda, [ptr; lsl_const c (log2size - 1)]);
288 Cconst_int((n-1) lsl (log2size - 1))])
290 Cop(Cadda, [Cop(Cadda, [ptr; lsl_const ofs (log2size - 1)]);
291 Cconst_int((-1) lsl (log2size - 1))])
293 let addr_array_ref arr ofs =
294 Cop(Cload Word, [array_indexing log2_size_addr arr ofs])
295 let unboxed_float_array_ref arr ofs =
296 Cop(Cload Double_u, [array_indexing log2_size_float arr ofs])
297 let float_array_ref arr ofs =
298 box_float(unboxed_float_array_ref arr ofs)
300 let addr_array_set arr ofs newval =
301 Cop(Cextcall("caml_modify", typ_void, false, Debuginfo.none),
302 [array_indexing log2_size_addr arr ofs; newval])
303 let int_array_set arr ofs newval =
304 Cop(Cstore Word, [array_indexing log2_size_addr arr ofs; newval])
305 let float_array_set arr ofs newval =
306 Cop(Cstore Double_u, [array_indexing log2_size_float arr ofs; newval])
310 let string_length exp =
311 bind "str" exp (fun str ->
312 let tmp_var = Ident.create "tmp" in
316 [Cop(Clsr, [header str; Cconst_int 10]);
317 Cconst_int log2_size_addr]);
321 Cop(Cload Byte_unsigned,
322 [Cop(Cadda, [str; Cvar tmp_var])])])))
324 (* Message sending *)
326 let lookup_tag obj tag =
327 bind "tag" tag (fun tag ->
328 Cop(Cextcall("caml_get_public_method", typ_addr, false, Debuginfo.none),
331 let lookup_label obj lab =
332 bind "lab" lab (fun lab ->
333 let table = Cop (Cload Word, [obj]) in
334 addr_array_ref table lab)
336 let call_cached_method obj tag cache pos args dbg =
337 let arity = List.length args in
338 let cache = array_indexing log2_size_addr cache pos in
339 Compilenv.need_send_fun arity;
340 Cop(Capply (typ_addr, dbg),
341 Cconst_symbol("caml_send" ^ string_of_int arity) ::
342 obj :: tag :: cache :: args)
346 let make_alloc_generic set_fn tag wordsize args =
347 if wordsize <= Config.max_young_wosize then
348 Cop(Calloc, Cconst_natint(block_header tag wordsize) :: args)
350 let id = Ident.create "alloc" in
351 let rec fill_fields idx = function
353 | e1::el -> Csequence(set_fn (Cvar id) (Cconst_int idx) e1,
354 fill_fields (idx + 2) el) in
356 Cop(Cextcall("caml_alloc", typ_addr, true, Debuginfo.none),
357 [Cconst_int wordsize; Cconst_int tag]),
361 let make_alloc tag args =
362 make_alloc_generic addr_array_set tag (List.length args) args
363 let make_float_alloc tag args =
364 make_alloc_generic float_array_set tag
365 (List.length args * size_float / size_addr) args
367 (* To compile "let rec" over values *)
369 let fundecls_size fundecls =
372 (fun (label, arity, params, body) ->
373 sz := !sz + 1 + (if arity = 1 then 2 else 3))
381 let rec expr_size = function
382 | Uclosure(fundecls, clos_vars) ->
383 RHS_block (fundecls_size fundecls + List.length clos_vars)
384 | Ulet(id, exp, body) ->
386 | Uletrec(bindings, body) ->
388 | Uprim(Pmakeblock(tag, mut), args, _) ->
389 RHS_block (List.length args)
390 | Uprim(Pmakearray(Paddrarray | Pintarray), args, _) ->
391 RHS_block (List.length args)
392 | Usequence(exp, exp') ->
396 (* Record application and currying functions *)
398 let apply_function n =
399 Compilenv.need_apply_fun n; "caml_apply" ^ string_of_int n
400 let curry_function n =
401 Compilenv.need_curry_fun n;
403 then "caml_curry" ^ string_of_int n
404 else "caml_tuplify" ^ string_of_int (-n)
408 let transl_comparison = function
416 (* Translate structured constants *)
418 let const_label = ref 0
420 let new_const_label () =
424 let new_const_symbol () =
426 Compilenv.make_symbol (Some (string_of_int !const_label))
428 let structured_constants = ref ([] : (string * structured_constant) list)
430 let transl_constant = function
431 Const_base(Const_int n) ->
433 | Const_base(Const_char c) ->
434 Cconst_int(((Char.code c) lsl 1) + 1)
436 if n <= max_repr_int && n >= min_repr_int
437 then Cconst_pointer((n lsl 1) + 1)
438 else Cconst_natpointer
439 (Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
441 let lbl = new_const_symbol() in
442 structured_constants := (lbl, cst) :: !structured_constants;
445 (* Translate constant closures *)
447 let constant_closures =
448 ref ([] : (string * (string * int * Ident.t list * ulambda) list) list)
452 let box_int_constant bi n =
454 Pnativeint -> Const_base(Const_nativeint n)
455 | Pint32 -> Const_base(Const_int32 (Nativeint.to_int32 n))
456 | Pint64 -> Const_base(Const_int64 (Int64.of_nativeint n))
458 let operations_boxed_int bi =
460 Pnativeint -> "caml_nativeint_ops"
461 | Pint32 -> "caml_int32_ops"
462 | Pint64 -> "caml_int64_ops"
467 transl_constant (box_int_constant bi (Nativeint.of_int n))
469 transl_constant (box_int_constant bi n)
472 if bi = Pint32 && size_int = 8 && big_endian
473 then Cop(Clsl, [arg; Cconst_int 32])
475 Cop(Calloc, [alloc_boxedint_header;
476 Cconst_symbol(operations_boxed_int bi);
479 let rec unbox_int bi arg =
481 Cop(Calloc, [hdr; ops; Cop(Clsl, [contents; Cconst_int 32])])
482 when bi = Pint32 && size_int = 8 && big_endian ->
483 (* Force sign-extension of low 32 bits *)
484 Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32]); Cconst_int 32])
485 | Cop(Calloc, [hdr; ops; contents])
486 when bi = Pint32 && size_int = 8 && not big_endian ->
487 (* Force sign-extension of low 32 bits *)
488 Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32]); Cconst_int 32])
489 | Cop(Calloc, [hdr; ops; contents]) ->
491 | Clet(id, exp, body) -> Clet(id, exp, unbox_int bi body)
492 | Cifthenelse(cond, e1, e2) ->
493 Cifthenelse(cond, unbox_int bi e1, unbox_int bi e2)
494 | Csequence(e1, e2) -> Csequence(e1, unbox_int bi e2)
495 | Cswitch(e, tbl, el) -> Cswitch(e, tbl, Array.map (unbox_int bi) el)
496 | Ccatch(n, ids, e1, e2) -> Ccatch(n, ids, unbox_int bi e1, unbox_int bi e2)
497 | Ctrywith(e1, id, e2) -> Ctrywith(unbox_int bi e1, id, unbox_int bi e2)
499 Cop(Cload(if bi = Pint32 then Thirtytwo_signed else Word),
500 [Cop(Cadda, [arg; Cconst_int size_addr])])
502 let make_unsigned_int bi arg =
503 if bi = Pint32 && size_int = 8
504 then Cop(Cand, [arg; Cconst_natint 0xFFFFFFFFn])
509 let bigarray_elt_size = function
510 Pbigarray_unknown -> assert false
511 | Pbigarray_float32 -> 4
512 | Pbigarray_float64 -> 8
513 | Pbigarray_sint8 -> 1
514 | Pbigarray_uint8 -> 1
515 | Pbigarray_sint16 -> 2
516 | Pbigarray_uint16 -> 2
517 | Pbigarray_int32 -> 4
518 | Pbigarray_int64 -> 8
519 | Pbigarray_caml_int -> size_int
520 | Pbigarray_native_int -> size_int
521 | Pbigarray_complex32 -> 8
522 | Pbigarray_complex64 -> 16
524 let bigarray_indexing unsafe elt_kind layout b args dbg =
525 let check_bound a1 a2 k =
526 if unsafe then k else Csequence(Cop(Ccheckbound dbg, [a1;a2]), k) in
527 let rec ba_indexing dim_ofs delta_ofs = function
530 bind "idx" (untag_int arg)
532 check_bound (Cop(Cload Word,[field_address b dim_ofs])) idx idx)
534 let rem = ba_indexing (dim_ofs + delta_ofs) delta_ofs argl in
535 bind "idx" (untag_int arg1)
537 bind "bound" (Cop(Cload Word, [field_address b dim_ofs]))
539 check_bound bound idx (add_int (mul_int rem bound) idx))) in
542 Pbigarray_unknown_layout ->
544 | Pbigarray_c_layout ->
545 ba_indexing (4 + List.length args) (-1) (List.rev args)
546 | Pbigarray_fortran_layout ->
547 ba_indexing 5 1 (List.map (fun idx -> sub_int idx (Cconst_int 2)) args)
549 bigarray_elt_size elt_kind in
553 else Cop(Clsl, [offset; Cconst_int(log2 elt_size)]) in
554 Cop(Cadda, [Cop(Cload Word, [field_address b 1]); byte_offset])
556 let bigarray_word_kind = function
557 Pbigarray_unknown -> assert false
558 | Pbigarray_float32 -> Single
559 | Pbigarray_float64 -> Double
560 | Pbigarray_sint8 -> Byte_signed
561 | Pbigarray_uint8 -> Byte_unsigned
562 | Pbigarray_sint16 -> Sixteen_signed
563 | Pbigarray_uint16 -> Sixteen_unsigned
564 | Pbigarray_int32 -> Thirtytwo_signed
565 | Pbigarray_int64 -> Word
566 | Pbigarray_caml_int -> Word
567 | Pbigarray_native_int -> Word
568 | Pbigarray_complex32 -> Single
569 | Pbigarray_complex64 -> Double
571 let bigarray_get unsafe elt_kind layout b args dbg =
573 Pbigarray_complex32 | Pbigarray_complex64 ->
574 let kind = bigarray_word_kind elt_kind in
575 let sz = bigarray_elt_size elt_kind / 2 in
576 bind "addr" (bigarray_indexing unsafe elt_kind layout b args dbg) (fun addr ->
578 (Cop(Cload kind, [addr]))
579 (Cop(Cload kind, [Cop(Cadda, [addr; Cconst_int sz])])))
581 Cop(Cload (bigarray_word_kind elt_kind),
582 [bigarray_indexing unsafe elt_kind layout b args dbg])
584 let bigarray_set unsafe elt_kind layout b args newval dbg =
586 Pbigarray_complex32 | Pbigarray_complex64 ->
587 let kind = bigarray_word_kind elt_kind in
588 let sz = bigarray_elt_size elt_kind / 2 in
589 bind "newval" newval (fun newv ->
590 bind "addr" (bigarray_indexing unsafe elt_kind layout b args dbg) (fun addr ->
592 Cop(Cstore kind, [addr; complex_re newv]),
594 [Cop(Cadda, [addr; Cconst_int sz]); complex_im newv]))))
596 Cop(Cstore (bigarray_word_kind elt_kind),
597 [bigarray_indexing unsafe elt_kind layout b args dbg; newval])
599 (* Simplification of some primitives into C calls *)
601 let default_prim name =
602 { prim_name = name; prim_arity = 0 (*ignored*);
603 prim_alloc = true; prim_native_name = ""; prim_native_float = false }
605 let simplif_primitive_32bits = function
606 Pbintofint Pint64 -> Pccall (default_prim "caml_int64_of_int")
607 | Pintofbint Pint64 -> Pccall (default_prim "caml_int64_to_int")
608 | Pcvtbint(Pint32, Pint64) -> Pccall (default_prim "caml_int64_of_int32")
609 | Pcvtbint(Pint64, Pint32) -> Pccall (default_prim "caml_int64_to_int32")
610 | Pcvtbint(Pnativeint, Pint64) ->
611 Pccall (default_prim "caml_int64_of_nativeint")
612 | Pcvtbint(Pint64, Pnativeint) ->
613 Pccall (default_prim "caml_int64_to_nativeint")
614 | Pnegbint Pint64 -> Pccall (default_prim "caml_int64_neg")
615 | Paddbint Pint64 -> Pccall (default_prim "caml_int64_add")
616 | Psubbint Pint64 -> Pccall (default_prim "caml_int64_sub")
617 | Pmulbint Pint64 -> Pccall (default_prim "caml_int64_mul")
618 | Pdivbint Pint64 -> Pccall (default_prim "caml_int64_div")
619 | Pmodbint Pint64 -> Pccall (default_prim "caml_int64_mod")
620 | Pandbint Pint64 -> Pccall (default_prim "caml_int64_and")
621 | Porbint Pint64 -> Pccall (default_prim "caml_int64_or")
622 | Pxorbint Pint64 -> Pccall (default_prim "caml_int64_xor")
623 | Plslbint Pint64 -> Pccall (default_prim "caml_int64_shift_left")
624 | Plsrbint Pint64 -> Pccall (default_prim "caml_int64_shift_right_unsigned")
625 | Pasrbint Pint64 -> Pccall (default_prim "caml_int64_shift_right")
626 | Pbintcomp(Pint64, Lambda.Ceq) -> Pccall (default_prim "caml_equal")
627 | Pbintcomp(Pint64, Lambda.Cneq) -> Pccall (default_prim "caml_notequal")
628 | Pbintcomp(Pint64, Lambda.Clt) -> Pccall (default_prim "caml_lessthan")
629 | Pbintcomp(Pint64, Lambda.Cgt) -> Pccall (default_prim "caml_greaterthan")
630 | Pbintcomp(Pint64, Lambda.Cle) -> Pccall (default_prim "caml_lessequal")
631 | Pbintcomp(Pint64, Lambda.Cge) -> Pccall (default_prim "caml_greaterequal")
632 | Pbigarrayref(unsafe, n, Pbigarray_int64, layout) ->
633 Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
634 | Pbigarrayset(unsafe, n, Pbigarray_int64, layout) ->
635 Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
638 let simplif_primitive p =
641 Pccall (default_prim "caml_obj_dup")
642 | Pbigarrayref(unsafe, n, Pbigarray_unknown, layout) ->
643 Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
644 | Pbigarrayset(unsafe, n, Pbigarray_unknown, layout) ->
645 Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
646 | Pbigarrayref(unsafe, n, kind, Pbigarray_unknown_layout) ->
647 Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
648 | Pbigarrayset(unsafe, n, kind, Pbigarray_unknown_layout) ->
649 Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
651 if size_int = 8 then p else simplif_primitive_32bits p
653 (* Build switchers both for constants and blocks *)
655 (* constants first *)
657 let transl_isout h arg = tag_int (Cop(Ccmpa Clt, [h ; arg]))
659 exception Found of int
661 let make_switch_gen arg cases acts =
662 let lcases = Array.length cases in
663 let new_cases = Array.create lcases 0 in
664 let store = Switch.mk_store (=) in
666 for i = 0 to Array.length cases-1 do
667 let act = cases.(i) in
668 let new_act = store.Switch.act_store act in
669 new_cases.(i) <- new_act
675 (store.Switch.act_get ()))
678 (* Then for blocks *)
682 type primitive = operation
684 let eqint = Ccmpi Ceq
685 let neint = Ccmpi Cne
686 let leint = Ccmpi Cle
687 let ltint = Ccmpi Clt
688 let geint = Ccmpi Cge
689 let gtint = Ccmpi Cgt
691 type act = expression
693 let default = Cexit (0,[])
694 let make_prim p args = Cop (p,args)
695 let make_offset arg n = add_const arg n
696 let make_isout h arg = Cop (Ccmpa Clt, [h ; arg])
697 let make_isin h arg = Cop (Ccmpa Cge, [h ; arg])
698 let make_if cond ifso ifnot = Cifthenelse (cond, ifso, ifnot)
699 let make_switch arg cases actions =
700 make_switch_gen arg cases actions
701 let bind arg body = bind "switcher" arg body
705 module SwitcherBlocks = Switch.Make(SArgBlocks)
707 (* Auxiliary functions for optimizing "let" of boxed numbers (floats and
710 type unboxed_number_kind =
713 | Boxed_integer of boxed_integer
715 let is_unboxed_number = function
716 Uconst(Const_base(Const_float f)) ->
719 begin match simplif_primitive p with
720 Pccall p -> if p.prim_native_float then Boxed_float else No_unboxing
721 | Pfloatfield _ -> Boxed_float
722 | Pfloatofint -> Boxed_float
723 | Pnegfloat -> Boxed_float
724 | Pabsfloat -> Boxed_float
725 | Paddfloat -> Boxed_float
726 | Psubfloat -> Boxed_float
727 | Pmulfloat -> Boxed_float
728 | Pdivfloat -> Boxed_float
729 | Parrayrefu Pfloatarray -> Boxed_float
730 | Parrayrefs Pfloatarray -> Boxed_float
731 | Pbintofint bi -> Boxed_integer bi
732 | Pcvtbint(src, dst) -> Boxed_integer dst
733 | Pnegbint bi -> Boxed_integer bi
734 | Paddbint bi -> Boxed_integer bi
735 | Psubbint bi -> Boxed_integer bi
736 | Pmulbint bi -> Boxed_integer bi
737 | Pdivbint bi -> Boxed_integer bi
738 | Pmodbint bi -> Boxed_integer bi
739 | Pandbint bi -> Boxed_integer bi
740 | Porbint bi -> Boxed_integer bi
741 | Pxorbint bi -> Boxed_integer bi
742 | Plslbint bi -> Boxed_integer bi
743 | Plsrbint bi -> Boxed_integer bi
744 | Pasrbint bi -> Boxed_integer bi
745 | Pbigarrayref(_, _, (Pbigarray_float32 | Pbigarray_float64), _) ->
747 | Pbigarrayref(_, _, Pbigarray_int32, _) -> Boxed_integer Pint32
748 | Pbigarrayref(_, _, Pbigarray_int64, _) -> Boxed_integer Pint64
749 | Pbigarrayref(_, _, Pbigarray_native_int, _) -> Boxed_integer Pnativeint
754 let subst_boxed_number unbox_fn boxed_id unboxed_id exp =
755 let need_boxed = ref false in
756 let assigned = ref false in
757 let rec subst = function
759 if Ident.same id boxed_id then need_boxed := true; e
760 | Clet(id, arg, body) -> Clet(id, subst arg, subst body)
761 | Cassign(id, arg) ->
762 if Ident.same id boxed_id then begin
764 Cassign(unboxed_id, subst(unbox_fn arg))
766 Cassign(id, subst arg)
767 | Ctuple argv -> Ctuple(List.map subst argv)
768 | Cop(Cload _, [Cvar id]) as e ->
769 if Ident.same id boxed_id then Cvar unboxed_id else e
770 | Cop(Cload _, [Cop(Cadda, [Cvar id; _])]) as e ->
771 if Ident.same id boxed_id then Cvar unboxed_id else e
772 | Cop(op, argv) -> Cop(op, List.map subst argv)
773 | Csequence(e1, e2) -> Csequence(subst e1, subst e2)
774 | Cifthenelse(e1, e2, e3) -> Cifthenelse(subst e1, subst e2, subst e3)
775 | Cswitch(arg, index, cases) ->
776 Cswitch(subst arg, index, Array.map subst cases)
777 | Cloop e -> Cloop(subst e)
778 | Ccatch(nfail, ids, e1, e2) -> Ccatch(nfail, ids, subst e1, subst e2)
779 | Cexit (nfail, el) -> Cexit (nfail, List.map subst el)
780 | Ctrywith(e1, id, e2) -> Ctrywith(subst e1, id, subst e2)
782 let res = subst exp in
783 (res, !need_boxed, !assigned)
785 (* Translate an expression *)
787 let functions = (Queue.create() : (string * Ident.t list * ulambda) Queue.t)
789 let rec transl = function
794 | Uclosure(fundecls, []) ->
795 let lbl = new_const_symbol() in
796 constant_closures := (lbl, fundecls) :: !constant_closures;
798 (fun (label, arity, params, body) ->
799 Queue.add (label, params, body) functions)
802 | Uclosure(fundecls, clos_vars) ->
804 fundecls_size fundecls + List.length clos_vars in
805 let rec transl_fundecls pos = function
807 List.map transl clos_vars
808 | (label, arity, params, body) :: rem ->
809 Queue.add (label, params, body) functions;
812 then alloc_closure_header block_size
813 else alloc_infix_header pos in
816 Cconst_symbol label ::
818 transl_fundecls (pos + 3) rem
821 Cconst_symbol(curry_function arity) ::
823 Cconst_symbol label ::
824 transl_fundecls (pos + 4) rem in
825 Cop(Calloc, transl_fundecls 0 fundecls)
826 | Uoffset(arg, offset) ->
827 field_address (transl arg) offset
828 | Udirect_apply(lbl, args, dbg) ->
829 Cop(Capply(typ_addr, dbg), Cconst_symbol lbl :: List.map transl args)
830 | Ugeneric_apply(clos, [arg], dbg) ->
831 bind "fun" (transl clos) (fun clos ->
832 Cop(Capply(typ_addr, dbg), [get_field clos 0; transl arg; clos]))
833 | Ugeneric_apply(clos, args, dbg) ->
834 let arity = List.length args in
835 let cargs = Cconst_symbol(apply_function arity) ::
836 List.map transl (args @ [clos]) in
837 Cop(Capply(typ_addr, dbg), cargs)
838 | Usend(kind, met, obj, args, dbg) ->
839 let call_met obj args clos =
841 Cop(Capply(typ_addr, dbg), [get_field clos 0;obj;clos])
843 let arity = List.length args + 1 in
844 let cargs = Cconst_symbol(apply_function arity) :: obj ::
845 (List.map transl args) @ [clos] in
846 Cop(Capply(typ_addr, dbg), cargs)
848 bind "obj" (transl obj) (fun obj ->
849 match kind, args with
851 bind "met" (lookup_label obj (transl met)) (call_met obj args)
852 | Cached, cache :: pos :: args ->
853 call_cached_method obj (transl met) (transl cache) (transl pos)
854 (List.map transl args) dbg
856 bind "met" (lookup_tag obj (transl met)) (call_met obj args))
857 | Ulet(id, exp, body) ->
858 begin match is_unboxed_number exp with
860 Clet(id, transl exp, transl body)
862 transl_unbox_let box_float unbox_float transl_unbox_float
864 | Boxed_integer bi ->
865 transl_unbox_let (box_int bi) (unbox_int bi) (transl_unbox_int bi)
868 | Uletrec(bindings, body) ->
869 transl_letrec bindings (transl body)
872 | Uprim(prim, args, dbg) ->
873 begin match (simplif_primitive prim, args) with
874 (Pgetglobal id, []) ->
875 Cconst_symbol (Ident.name id)
876 | (Pmakeblock(tag, mut), []) ->
877 transl_constant(Const_block(tag, []))
878 | (Pmakeblock(tag, mut), args) ->
879 make_alloc tag (List.map transl args)
880 | (Pccall prim, args) ->
881 if prim.prim_native_float then
883 (Cop(Cextcall(prim.prim_native_name, typ_float, false, dbg),
884 List.map transl_unbox_float args))
886 Cop(Cextcall(Primitive.native_name prim, typ_addr, prim.prim_alloc, dbg),
887 List.map transl args)
888 | (Pmakearray kind, []) ->
889 transl_constant(Const_block(0, []))
890 | (Pmakearray kind, args) ->
891 begin match kind with
893 Cop(Cextcall("caml_make_array", typ_addr, true, Debuginfo.none),
894 [make_alloc 0 (List.map transl args)])
895 | Paddrarray | Pintarray ->
896 make_alloc 0 (List.map transl args)
898 make_float_alloc Obj.double_array_tag
899 (List.map transl_unbox_float args)
901 | (Pbigarrayref(unsafe, num_dims, elt_kind, layout), arg1 :: argl) ->
903 bigarray_get unsafe elt_kind layout
904 (transl arg1) (List.map transl argl) dbg in
905 begin match elt_kind with
906 Pbigarray_float32 | Pbigarray_float64 -> box_float elt
907 | Pbigarray_complex32 | Pbigarray_complex64 -> elt
908 | Pbigarray_int32 -> box_int Pint32 elt
909 | Pbigarray_int64 -> box_int Pint64 elt
910 | Pbigarray_native_int -> box_int Pnativeint elt
911 | Pbigarray_caml_int -> force_tag_int elt
914 | (Pbigarrayset(unsafe, num_dims, elt_kind, layout), arg1 :: argl) ->
915 let (argidx, argnewval) = split_last argl in
916 return_unit(bigarray_set unsafe elt_kind layout
918 (List.map transl argidx)
920 Pbigarray_float32 | Pbigarray_float64 ->
921 transl_unbox_float argnewval
922 | Pbigarray_complex32 | Pbigarray_complex64 -> transl argnewval
923 | Pbigarray_int32 -> transl_unbox_int Pint32 argnewval
924 | Pbigarray_int64 -> transl_unbox_int Pint64 argnewval
925 | Pbigarray_native_int -> transl_unbox_int Pnativeint argnewval
926 | _ -> untag_int (transl argnewval))
929 transl_prim_1 p arg dbg
930 | (p, [arg1; arg2]) ->
931 transl_prim_2 p arg1 arg2 dbg
932 | (p, [arg1; arg2; arg3]) ->
933 transl_prim_3 p arg1 arg2 arg3 dbg
935 fatal_error "Cmmgen.transl:prim"
938 (* Control structures *)
940 (* As in the bytecode interpreter, only matching against constants
942 if Array.length s.us_index_blocks = 0 then
944 (untag_int (transl arg),
946 Array.map transl s.us_actions_consts)
947 else if Array.length s.us_index_consts = 0 then
948 transl_switch (get_tag (transl arg))
949 s.us_index_blocks s.us_actions_blocks
951 bind "switch" (transl arg) (fun arg ->
953 Cop(Cand, [arg; Cconst_int 1]),
955 (untag_int arg) s.us_index_consts s.us_actions_consts,
957 (get_tag arg) s.us_index_blocks s.us_actions_blocks))
958 | Ustaticfail (nfail, args) ->
959 Cexit (nfail, List.map transl args)
960 | Ucatch(nfail, [], body, handler) ->
961 make_catch nfail (transl body) (transl handler)
962 | Ucatch(nfail, ids, body, handler) ->
963 Ccatch(nfail, ids, transl body, transl handler)
964 | Utrywith(body, exn, handler) ->
965 Ctrywith(transl body, exn, transl handler)
966 | Uifthenelse(Uprim(Pnot, [arg], _), ifso, ifnot) ->
967 transl (Uifthenelse(arg, ifnot, ifso))
968 | Uifthenelse(cond, ifso, Ustaticfail (nfail, [])) ->
969 exit_if_false cond (transl ifso) nfail
970 | Uifthenelse(cond, Ustaticfail (nfail, []), ifnot) ->
971 exit_if_true cond nfail (transl ifnot)
972 | Uifthenelse(Uprim(Psequand, _, _) as cond, ifso, ifnot) ->
973 let raise_num = next_raise_count () in
976 (exit_if_false cond (transl ifso) raise_num)
978 | Uifthenelse(Uprim(Psequor, _, _) as cond, ifso, ifnot) ->
979 let raise_num = next_raise_count () in
982 (exit_if_true cond raise_num (transl ifnot))
984 | Uifthenelse (Uifthenelse (cond, condso, condnot), ifso, ifnot) ->
985 let num_true = next_raise_count () in
991 (test_bool (transl cond),
992 exit_if_true condso num_true shared_false,
993 exit_if_true condnot num_true shared_false))
996 | Uifthenelse(cond, ifso, ifnot) ->
997 Cifthenelse(test_bool(transl cond), transl ifso, transl ifnot)
998 | Usequence(exp1, exp2) ->
999 Csequence(remove_unit(transl exp1), transl exp2)
1000 | Uwhile(cond, body) ->
1001 let raise_num = next_raise_count () in
1005 Cloop(exit_if_false cond (remove_unit(transl body)) raise_num),
1007 | Ufor(id, low, high, dir, body) ->
1008 let tst = match dir with Upto -> Cgt | Downto -> Clt in
1009 let inc = match dir with Upto -> Caddi | Downto -> Csubi in
1010 let raise_num = next_raise_count () in
1011 let id_prev = Ident.rename id in
1015 bind_nonvar "bound" (transl high) (fun high ->
1019 (Cop(Ccmpi tst, [Cvar id; high]), Cexit (raise_num, []),
1022 (remove_unit(transl body),
1023 Clet(id_prev, Cvar id,
1026 Cop(inc, [Cvar id; Cconst_int 2])),
1028 (Cop(Ccmpi Ceq, [Cvar id_prev; high]),
1029 Cexit (raise_num,[]), Ctuple [])))))),
1031 | Uassign(id, exp) ->
1032 return_unit(Cassign(id, transl exp))
1034 and transl_prim_1 p arg dbg =
1036 (* Generic operations *)
1040 return_unit(remove_unit (transl arg))
1041 (* Heap operations *)
1043 get_field (transl arg) n
1045 let ptr = transl arg in
1049 else Cop(Cadda, [ptr; Cconst_int(n * size_float)])]))
1052 Cop(Craise dbg, [transl arg])
1053 (* Integer operations *)
1055 Cop(Csubi, [Cconst_int 2; transl arg])
1057 if no_overflow_lsl n then
1058 add_const (transl arg) (n lsl 1)
1060 transl_prim_2 Paddint arg (Uconst (Const_base(Const_int n))) Debuginfo.none
1063 (bind "ref" (transl arg) (fun arg ->
1065 [arg; add_const (Cop(Cload Word, [arg])) (n lsl 1)])))
1066 (* Floating-point operations *)
1068 box_float(Cop(Cfloatofint, [untag_int(transl arg)]))
1070 tag_int(Cop(Cintoffloat, [transl_unbox_float arg]))
1072 box_float(Cop(Cnegf, [transl_unbox_float arg]))
1074 box_float(Cop(Cabsf, [transl_unbox_float arg]))
1075 (* String operations *)
1077 tag_int(string_length (transl arg))
1078 (* Array operations *)
1079 | Parraylength kind ->
1080 begin match kind with
1083 if wordsize_shift = numfloat_shift then
1084 Cop(Clsr, [header(transl arg); Cconst_int wordsize_shift])
1086 bind "header" (header(transl arg)) (fun hdr ->
1087 Cifthenelse(is_addr_array_hdr hdr,
1088 Cop(Clsr, [hdr; Cconst_int wordsize_shift]),
1089 Cop(Clsr, [hdr; Cconst_int numfloat_shift]))) in
1090 Cop(Cor, [len; Cconst_int 1])
1091 | Paddrarray | Pintarray ->
1092 Cop(Cor, [addr_array_length(header(transl arg)); Cconst_int 1])
1094 Cop(Cor, [float_array_length(header(transl arg)); Cconst_int 1])
1096 (* Boolean operations *)
1098 Cop(Csubi, [Cconst_int 4; transl arg]) (* 1 -> 3, 3 -> 1 *)
1099 (* Test integer/block *)
1101 tag_int(Cop(Cand, [transl arg; Cconst_int 1]))
1102 (* Boxed integers *)
1104 box_int bi (untag_int (transl arg))
1106 force_tag_int (transl_unbox_int bi arg)
1107 | Pcvtbint(bi1, bi2) ->
1108 box_int bi2 (transl_unbox_int bi1 arg)
1110 box_int bi (Cop(Csubi, [Cconst_int 0; transl_unbox_int bi arg]))
1112 fatal_error "Cmmgen.transl_prim_1"
1114 and transl_prim_2 p arg1 arg2 dbg =
1116 (* Heap operations *)
1117 Psetfield(n, ptr) ->
1119 return_unit(Cop(Cextcall("caml_modify", typ_void, false, Debuginfo.none),
1120 [field_address (transl arg1) n; transl arg2]))
1122 return_unit(set_field (transl arg1) n (transl arg2))
1123 | Psetfloatfield n ->
1124 let ptr = transl arg1 in
1126 Cop(Cstore Double_u,
1128 else Cop(Cadda, [ptr; Cconst_int(n * size_float)]);
1129 transl_unbox_float arg2]))
1131 (* Boolean operations *)
1133 Cifthenelse(test_bool(transl arg1), transl arg2, Cconst_int 1)
1134 (* let id = Ident.create "res1" in
1135 Clet(id, transl arg1,
1136 Cifthenelse(test_bool(Cvar id), transl arg2, Cvar id)) *)
1138 Cifthenelse(test_bool(transl arg1), Cconst_int 3, transl arg2)
1140 (* Integer operations *)
1142 decr_int(add_int (transl arg1) (transl arg2))
1144 incr_int(sub_int (transl arg1) (transl arg2))
1146 incr_int(Cop(Cmuli, [decr_int(transl arg1); untag_int(transl arg2)]))
1148 tag_int(safe_divmod Cdivi (untag_int(transl arg1)) (untag_int(transl arg2)) dbg)
1150 tag_int(safe_divmod Cmodi (untag_int(transl arg1)) (untag_int(transl arg2)) dbg)
1152 Cop(Cand, [transl arg1; transl arg2])
1154 Cop(Cor, [transl arg1; transl arg2])
1156 Cop(Cor, [Cop(Cxor, [ignore_low_bit_int(transl arg1);
1157 ignore_low_bit_int(transl arg2)]);
1160 incr_int(lsl_int (decr_int(transl arg1)) (untag_int(transl arg2)))
1162 Cop(Cor, [Cop(Clsr, [transl arg1; untag_int(transl arg2)]);
1165 Cop(Cor, [Cop(Casr, [transl arg1; untag_int(transl arg2)]);
1168 tag_int(Cop(Ccmpi(transl_comparison cmp), [transl arg1; transl arg2]))
1170 transl_isout (transl arg1) (transl arg2)
1171 (* Float operations *)
1173 box_float(Cop(Caddf,
1174 [transl_unbox_float arg1; transl_unbox_float arg2]))
1176 box_float(Cop(Csubf,
1177 [transl_unbox_float arg1; transl_unbox_float arg2]))
1179 box_float(Cop(Cmulf,
1180 [transl_unbox_float arg1; transl_unbox_float arg2]))
1182 box_float(Cop(Cdivf,
1183 [transl_unbox_float arg1; transl_unbox_float arg2]))
1185 tag_int(Cop(Ccmpf(transl_comparison cmp),
1186 [transl_unbox_float arg1; transl_unbox_float arg2]))
1188 (* String operations *)
1190 tag_int(Cop(Cload Byte_unsigned,
1191 [add_int (transl arg1) (untag_int(transl arg2))]))
1194 (bind "str" (transl arg1) (fun str ->
1195 bind "index" (untag_int (transl arg2)) (fun idx ->
1197 Cop(Ccheckbound dbg, [string_length str; idx]),
1198 Cop(Cload Byte_unsigned, [add_int str idx])))))
1200 (* Array operations *)
1201 | Parrayrefu kind ->
1202 begin match kind with
1204 bind "arr" (transl arg1) (fun arr ->
1205 bind "index" (transl arg2) (fun idx ->
1206 Cifthenelse(is_addr_array_ptr arr,
1207 addr_array_ref arr idx,
1208 float_array_ref arr idx)))
1209 | Paddrarray | Pintarray ->
1210 addr_array_ref (transl arg1) (transl arg2)
1212 float_array_ref (transl arg1) (transl arg2)
1214 | Parrayrefs kind ->
1215 begin match kind with
1217 bind "index" (transl arg2) (fun idx ->
1218 bind "arr" (transl arg1) (fun arr ->
1219 bind "header" (header arr) (fun hdr ->
1220 Cifthenelse(is_addr_array_hdr hdr,
1221 Csequence(Cop(Ccheckbound dbg, [addr_array_length hdr; idx]),
1222 addr_array_ref arr idx),
1223 Csequence(Cop(Ccheckbound dbg, [float_array_length hdr; idx]),
1224 float_array_ref arr idx)))))
1225 | Paddrarray | Pintarray ->
1226 bind "index" (transl arg2) (fun idx ->
1227 bind "arr" (transl arg1) (fun arr ->
1228 Csequence(Cop(Ccheckbound dbg, [addr_array_length(header arr); idx]),
1229 addr_array_ref arr idx)))
1232 bind "index" (transl arg2) (fun idx ->
1233 bind "arr" (transl arg1) (fun arr ->
1234 Csequence(Cop(Ccheckbound dbg,
1235 [float_array_length(header arr); idx]),
1236 unboxed_float_array_ref arr idx))))
1239 (* Operations on bitvects *)
1241 bind "index" (untag_int(transl arg2)) (fun idx ->
1243 Cop(Cand, [Cop(Clsr, [Cop(Cload Byte_unsigned,
1244 [add_int (transl arg1)
1245 (Cop(Clsr, [idx; Cconst_int 3]))]);
1246 Cop(Cand, [idx; Cconst_int 7])]);
1249 (* Boxed integers *)
1251 box_int bi (Cop(Caddi,
1252 [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
1254 box_int bi (Cop(Csubi,
1255 [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
1257 box_int bi (Cop(Cmuli,
1258 [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
1260 box_int bi (safe_divmod Cdivi
1261 (transl_unbox_int bi arg1) (transl_unbox_int bi arg2)
1264 box_int bi (safe_divmod Cmodi
1265 (transl_unbox_int bi arg1) (transl_unbox_int bi arg2)
1268 box_int bi (Cop(Cand,
1269 [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
1271 box_int bi (Cop(Cor,
1272 [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
1274 box_int bi (Cop(Cxor,
1275 [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
1277 box_int bi (Cop(Clsl,
1278 [transl_unbox_int bi arg1; untag_int(transl arg2)]))
1280 box_int bi (Cop(Clsr,
1281 [make_unsigned_int bi (transl_unbox_int bi arg1);
1282 untag_int(transl arg2)]))
1284 box_int bi (Cop(Casr,
1285 [transl_unbox_int bi arg1; untag_int(transl arg2)]))
1286 | Pbintcomp(bi, cmp) ->
1287 tag_int (Cop(Ccmpi(transl_comparison cmp),
1288 [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
1290 fatal_error "Cmmgen.transl_prim_2"
1292 and transl_prim_3 p arg1 arg2 arg3 dbg =
1294 (* String operations *)
1296 return_unit(Cop(Cstore Byte_unsigned,
1297 [add_int (transl arg1) (untag_int(transl arg2));
1298 untag_int(transl arg3)]))
1301 (bind "str" (transl arg1) (fun str ->
1302 bind "index" (untag_int (transl arg2)) (fun idx ->
1304 Cop(Ccheckbound dbg, [string_length str; idx]),
1305 Cop(Cstore Byte_unsigned,
1306 [add_int str idx; untag_int(transl arg3)])))))
1308 (* Array operations *)
1309 | Parraysetu kind ->
1310 return_unit(begin match kind with
1312 bind "newval" (transl arg3) (fun newval ->
1313 bind "index" (transl arg2) (fun index ->
1314 bind "arr" (transl arg1) (fun arr ->
1315 Cifthenelse(is_addr_array_ptr arr,
1316 addr_array_set arr index newval,
1317 float_array_set arr index (unbox_float newval)))))
1319 addr_array_set (transl arg1) (transl arg2) (transl arg3)
1321 int_array_set (transl arg1) (transl arg2) (transl arg3)
1323 float_array_set (transl arg1) (transl arg2) (transl_unbox_float arg3)
1325 | Parraysets kind ->
1326 return_unit(begin match kind with
1328 bind "newval" (transl arg3) (fun newval ->
1329 bind "index" (transl arg2) (fun idx ->
1330 bind "arr" (transl arg1) (fun arr ->
1331 bind "header" (header arr) (fun hdr ->
1332 Cifthenelse(is_addr_array_hdr hdr,
1333 Csequence(Cop(Ccheckbound dbg, [addr_array_length hdr; idx]),
1334 addr_array_set arr idx newval),
1335 Csequence(Cop(Ccheckbound dbg, [float_array_length hdr; idx]),
1336 float_array_set arr idx
1337 (unbox_float newval)))))))
1339 bind "index" (transl arg2) (fun idx ->
1340 bind "arr" (transl arg1) (fun arr ->
1341 Csequence(Cop(Ccheckbound dbg, [addr_array_length(header arr); idx]),
1342 addr_array_set arr idx (transl arg3))))
1344 bind "index" (transl arg2) (fun idx ->
1345 bind "arr" (transl arg1) (fun arr ->
1346 Csequence(Cop(Ccheckbound dbg, [addr_array_length(header arr); idx]),
1347 int_array_set arr idx (transl arg3))))
1349 bind "index" (transl arg2) (fun idx ->
1350 bind "arr" (transl arg1) (fun arr ->
1351 Csequence(Cop(Ccheckbound dbg, [float_array_length(header arr);idx]),
1352 float_array_set arr idx (transl_unbox_float arg3))))
1355 fatal_error "Cmmgen.transl_prim_3"
1357 and transl_unbox_float = function
1358 Uconst(Const_base(Const_float f)) -> Cconst_float f
1359 | exp -> unbox_float(transl exp)
1361 and transl_unbox_int bi = function
1362 Uconst(Const_base(Const_int32 n)) ->
1363 Cconst_natint (Nativeint.of_int32 n)
1364 | Uconst(Const_base(Const_nativeint n)) ->
1366 | Uconst(Const_base(Const_int64 n)) ->
1367 assert (size_int = 8); Cconst_natint (Int64.to_nativeint n)
1368 | Uprim(Pbintofint bi', [Uconst(Const_base(Const_int i))], _) when bi = bi' ->
1370 | exp -> unbox_int bi (transl exp)
1372 and transl_unbox_let box_fn unbox_fn transl_unbox_fn id exp body =
1373 let unboxed_id = Ident.create (Ident.name id) in
1374 let trbody1 = transl body in
1375 let (trbody2, need_boxed, is_assigned) =
1376 subst_boxed_number unbox_fn id unboxed_id trbody1 in
1377 if need_boxed && is_assigned then
1378 Clet(id, transl exp, trbody1)
1380 Clet(unboxed_id, transl_unbox_fn exp,
1382 then Clet(id, box_fn(Cvar unboxed_id), trbody2)
1385 and make_catch ncatch body handler = match body with
1386 | Cexit (nexit,[]) when nexit=ncatch -> handler
1387 | _ -> Ccatch (ncatch, [], body, handler)
1389 and make_catch2 mk_body handler = match handler with
1390 | Cexit (_,[])|Ctuple []|Cconst_int _|Cconst_pointer _ ->
1393 let nfail = next_raise_count () in
1396 (mk_body (Cexit (nfail,[])))
1399 and exit_if_true cond nfail otherwise =
1401 | Uconst (Const_pointer 0) -> otherwise
1402 | Uconst (Const_pointer 1) -> Cexit (nfail,[])
1403 | Uprim(Psequor, [arg1; arg2], _) ->
1404 exit_if_true arg1 nfail (exit_if_true arg2 nfail otherwise)
1405 | Uprim(Psequand, _, _) ->
1406 begin match otherwise with
1407 | Cexit (raise_num,[]) ->
1408 exit_if_false cond (Cexit (nfail,[])) raise_num
1410 let raise_num = next_raise_count () in
1413 (exit_if_false cond (Cexit (nfail,[])) raise_num)
1416 | Uprim(Pnot, [arg], _) ->
1417 exit_if_false arg otherwise nfail
1418 | Uifthenelse (cond, ifso, ifnot) ->
1422 (test_bool (transl cond),
1423 exit_if_true ifso nfail shared,
1424 exit_if_true ifnot nfail shared))
1427 Cifthenelse(test_bool(transl cond), Cexit (nfail, []), otherwise)
1429 and exit_if_false cond otherwise nfail =
1431 | Uconst (Const_pointer 0) -> Cexit (nfail,[])
1432 | Uconst (Const_pointer 1) -> otherwise
1433 | Uprim(Psequand, [arg1; arg2], _) ->
1434 exit_if_false arg1 (exit_if_false arg2 otherwise nfail) nfail
1435 | Uprim(Psequor, _, _) ->
1436 begin match otherwise with
1437 | Cexit (raise_num,[]) ->
1438 exit_if_true cond raise_num (Cexit (nfail,[]))
1440 let raise_num = next_raise_count () in
1443 (exit_if_true cond raise_num (Cexit (nfail,[])))
1446 | Uprim(Pnot, [arg], _) ->
1447 exit_if_true arg nfail otherwise
1448 | Uifthenelse (cond, ifso, ifnot) ->
1452 (test_bool (transl cond),
1453 exit_if_false ifso shared nfail,
1454 exit_if_false ifnot shared nfail))
1457 Cifthenelse(test_bool(transl cond), otherwise, Cexit (nfail, []))
1459 and transl_switch arg index cases = match Array.length cases with
1460 | 0 -> fatal_error "Cmmgen.transl_switch"
1461 | 1 -> transl cases.(0)
1463 let n_index = Array.length index in
1464 let actions = Array.map transl cases in
1467 and this_high = ref (n_index-1)
1468 and this_low = ref (n_index-1)
1469 and this_act = ref index.(n_index-1) in
1470 for i = n_index-2 downto 0 do
1471 let act = index.(i) in
1472 if act = !this_act then
1475 inters := (!this_low, !this_high, !this_act) :: !inters ;
1481 inters := (0, !this_high, !this_act) :: !inters ;
1486 (fun i -> Cconst_int i)
1488 (Array.of_list !inters) actions)
1490 and transl_letrec bindings cont =
1491 let bsz = List.map (fun (id, exp) -> (id, exp, expr_size exp)) bindings in
1492 let rec init_blocks = function
1493 | [] -> fill_nonrec bsz
1494 | (id, exp, RHS_block sz) :: rem ->
1495 Clet(id, Cop(Cextcall("caml_alloc_dummy", typ_addr, true, Debuginfo.none),
1498 | (id, exp, RHS_nonrec) :: rem ->
1499 Clet (id, Cconst_int 0, init_blocks rem)
1500 and fill_nonrec = function
1501 | [] -> fill_blocks bsz
1502 | (id, exp, RHS_block sz) :: rem -> fill_nonrec rem
1503 | (id, exp, RHS_nonrec) :: rem ->
1504 Clet (id, transl exp, fill_nonrec rem)
1505 and fill_blocks = function
1507 | (id, exp, RHS_block _) :: rem ->
1508 Csequence(Cop(Cextcall("caml_update_dummy", typ_void, false, Debuginfo.none),
1509 [Cvar id; transl exp]),
1511 | (id, exp, RHS_nonrec) :: rem ->
1515 (* Translate a function definition *)
1517 let transl_function lbl params body =
1518 Cfunction {fun_name = lbl;
1519 fun_args = List.map (fun id -> (id, typ_addr)) params;
1520 fun_body = transl body;
1521 fun_fast = !Clflags.optimize_for_speed}
1523 (* Translate all function definitions *)
1528 let compare = compare
1531 let rec transl_all_functions already_translated cont =
1533 let (lbl, params, body) = Queue.take functions in
1534 if StringSet.mem lbl already_translated then
1535 transl_all_functions already_translated cont
1537 transl_all_functions (StringSet.add lbl already_translated)
1538 (transl_function lbl params body :: cont)
1543 (* Emit structured constants *)
1545 let immstrings = Hashtbl.create 17
1547 let rec emit_constant symb cst cont =
1549 Const_base(Const_float s) ->
1550 Cint(float_header) :: Cdefine_symbol symb :: Cdouble s :: cont
1551 | Const_base(Const_string s) | Const_immstring s ->
1552 Cint(string_header (String.length s)) ::
1553 Cdefine_symbol symb ::
1554 emit_string_constant s cont
1555 | Const_base(Const_int32 n) ->
1556 Cint(boxedint_header) :: Cdefine_symbol symb ::
1557 emit_boxed_int32_constant n cont
1558 | Const_base(Const_int64 n) ->
1559 Cint(boxedint_header) :: Cdefine_symbol symb ::
1560 emit_boxed_int64_constant n cont
1561 | Const_base(Const_nativeint n) ->
1562 Cint(boxedint_header) :: Cdefine_symbol symb ::
1563 emit_boxed_nativeint_constant n cont
1564 | Const_block(tag, fields) ->
1565 let (emit_fields, cont1) = emit_constant_fields fields cont in
1566 Cint(block_header tag (List.length fields)) ::
1567 Cdefine_symbol symb ::
1569 | Const_float_array(fields) ->
1570 Cint(floatarray_header (List.length fields)) ::
1571 Cdefine_symbol symb ::
1572 Misc.map_end (fun f -> Cdouble f) fields cont
1573 | _ -> fatal_error "gencmm.emit_constant"
1575 and emit_constant_fields fields cont =
1579 let (data1, cont1) = emit_constant_field f1 cont in
1580 let (datal, contl) = emit_constant_fields fl cont1 in
1581 (data1 :: datal, contl)
1583 and emit_constant_field field cont =
1585 Const_base(Const_int n) ->
1586 (Cint(Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n),
1588 | Const_base(Const_char c) ->
1589 (Cint(Nativeint.of_int(((Char.code c) lsl 1) + 1)), cont)
1590 | Const_base(Const_float s) ->
1591 let lbl = new_const_label() in
1592 (Clabel_address lbl,
1593 Cint(float_header) :: Cdefine_label lbl :: Cdouble s :: cont)
1594 | Const_base(Const_string s) ->
1595 let lbl = new_const_label() in
1596 (Clabel_address lbl,
1597 Cint(string_header (String.length s)) :: Cdefine_label lbl ::
1598 emit_string_constant s cont)
1599 | Const_immstring s ->
1601 (Clabel_address (Hashtbl.find immstrings s), cont)
1603 let lbl = new_const_label() in
1604 Hashtbl.add immstrings s lbl;
1605 (Clabel_address lbl,
1606 Cint(string_header (String.length s)) :: Cdefine_label lbl ::
1607 emit_string_constant s cont)
1609 | Const_base(Const_int32 n) ->
1610 let lbl = new_const_label() in
1611 (Clabel_address lbl,
1612 Cint(boxedint_header) :: Cdefine_label lbl ::
1613 emit_boxed_int32_constant n cont)
1614 | Const_base(Const_int64 n) ->
1615 let lbl = new_const_label() in
1616 (Clabel_address lbl,
1617 Cint(boxedint_header) :: Cdefine_label lbl ::
1618 emit_boxed_int64_constant n cont)
1619 | Const_base(Const_nativeint n) ->
1620 let lbl = new_const_label() in
1621 (Clabel_address lbl,
1622 Cint(boxedint_header) :: Cdefine_label lbl ::
1623 emit_boxed_nativeint_constant n cont)
1624 | Const_pointer n ->
1625 (Cint(Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n),
1627 | Const_block(tag, fields) ->
1628 let lbl = new_const_label() in
1629 let (emit_fields, cont1) = emit_constant_fields fields cont in
1630 (Clabel_address lbl,
1631 Cint(block_header tag (List.length fields)) :: Cdefine_label lbl ::
1632 emit_fields @ cont1)
1633 | Const_float_array(fields) ->
1634 let lbl = new_const_label() in
1635 (Clabel_address lbl,
1636 Cint(floatarray_header (List.length fields)) :: Cdefine_label lbl ::
1637 Misc.map_end (fun f -> Cdouble f) fields cont)
1639 and emit_string_constant s cont =
1640 let n = size_int - 1 - (String.length s) mod size_int in
1641 Cstring s :: Cskip n :: Cint8 n :: cont
1643 and emit_boxed_int32_constant n cont =
1644 let n = Nativeint.of_int32 n in
1645 if size_int = 8 then
1646 Csymbol_address("caml_int32_ops") :: Cint32 n :: Cint32 0n :: cont
1648 Csymbol_address("caml_int32_ops") :: Cint n :: cont
1650 and emit_boxed_nativeint_constant n cont =
1651 Csymbol_address("caml_nativeint_ops") :: Cint n :: cont
1653 and emit_boxed_int64_constant n cont =
1654 let lo = Int64.to_nativeint n in
1655 if size_int = 8 then
1656 Csymbol_address("caml_int64_ops") :: Cint lo :: cont
1658 let hi = Int64.to_nativeint (Int64.shift_right n 32) in
1660 Csymbol_address("caml_int64_ops") :: Cint hi :: Cint lo :: cont
1662 Csymbol_address("caml_int64_ops") :: Cint lo :: Cint hi :: cont
1665 (* Emit constant closures *)
1667 let emit_constant_closure symb fundecls cont =
1670 | (label, arity, params, body) :: remainder ->
1671 let rec emit_others pos = function
1673 | (label, arity, params, body) :: rem ->
1675 Cint(infix_header pos) ::
1676 Csymbol_address label ::
1678 emit_others (pos + 3) rem
1680 Cint(infix_header pos) ::
1681 Csymbol_address(curry_function arity) ::
1682 Cint(Nativeint.of_int (arity lsl 1 + 1)) ::
1683 Csymbol_address label ::
1684 emit_others (pos + 4) rem in
1685 Cint(closure_header (fundecls_size fundecls)) ::
1686 Cdefine_symbol symb ::
1688 Csymbol_address label ::
1690 emit_others 3 remainder
1692 Csymbol_address(curry_function arity) ::
1693 Cint(Nativeint.of_int (arity lsl 1 + 1)) ::
1694 Csymbol_address label ::
1695 emit_others 4 remainder
1697 (* Emit all structured constants *)
1699 let emit_all_constants cont =
1702 (fun (lbl, cst) -> c := Cdata(emit_constant lbl cst []) :: !c)
1703 !structured_constants;
1704 structured_constants := [];
1705 Hashtbl.clear immstrings; (* PR#3979 *)
1707 (fun (symb, fundecls) ->
1708 c := Cdata(emit_constant_closure symb fundecls []) :: !c)
1710 constant_closures := [];
1713 (* Translate a compilation unit *)
1715 let compunit size ulam =
1716 let glob = Compilenv.make_symbol None in
1717 let init_code = transl ulam in
1718 let c1 = [Cfunction {fun_name = Compilenv.make_symbol (Some "entry");
1720 fun_body = init_code; fun_fast = false}] in
1721 let c2 = transl_all_functions StringSet.empty c1 in
1722 let c3 = emit_all_constants c2 in
1723 Cdata [Cint(block_header 0 size);
1724 Cglobal_symbol glob;
1725 Cdefine_symbol glob;
1726 Cskip(size * size_addr)] :: c3
1729 CAMLprim value caml_cache_public_method (value meths, value tag, value *cache)
1731 int li = 3, hi = Field(meths,0), mi;
1732 while (li < hi) { // no need to check the 1st time
1733 mi = ((li+hi) >> 1) | 1;
1734 if (tag < Field(meths,mi)) hi = mi-2;
1737 *cache = (li-3)*sizeof(value)+1;
1738 return Field (meths, li-1);
1742 let cache_public_method meths tag cache =
1743 let raise_num = next_raise_count () in
1744 let li = Ident.create "li" and hi = Ident.create "hi"
1745 and mi = Ident.create "mi" and tagged = Ident.create "tagged" in
1749 hi, Cop(Cload Word, [meths]),
1757 [Cop(Clsr, [Cop(Caddi, [Cvar li; Cvar hi]); Cconst_int 1]);
1765 [meths; lsl_const (Cvar mi) log2_size_addr])])]),
1766 Cassign(hi, Cop(Csubi, [Cvar mi; Cconst_int 2])),
1767 Cassign(li, Cvar mi)),
1769 (Cop(Ccmpi Cge, [Cvar li; Cvar hi]), Cexit (raise_num, []),
1773 tagged, Cop(Cadda, [lsl_const (Cvar li) log2_size_addr;
1774 Cconst_int(1 - 3 * size_addr)]),
1775 Csequence(Cop (Cstore Word, [cache; Cvar tagged]),
1778 (* Generate an application function:
1779 (defun caml_applyN (a1 ... aN clos)
1780 (if (= clos.arity N)
1781 (app clos.direct a1 ... aN clos)
1782 (let (clos1 (app clos.code a1 clos)
1783 clos2 (app clos1.code a2 clos)
1785 closN-1 (app closN-2.code aN-1 closN-2))
1786 (app closN-1.code aN closN-1))))
1789 let apply_function_body arity =
1790 let arg = Array.create arity (Ident.create "arg") in
1791 for i = 1 to arity - 1 do arg.(i) <- Ident.create "arg" done;
1792 let clos = Ident.create "clos" in
1793 let rec app_fun clos n =
1795 Cop(Capply(typ_addr, Debuginfo.none),
1796 [get_field (Cvar clos) 0; Cvar arg.(n); Cvar clos])
1798 let newclos = Ident.create "clos" in
1800 Cop(Capply(typ_addr, Debuginfo.none),
1801 [get_field (Cvar clos) 0; Cvar arg.(n); Cvar clos]),
1802 app_fun newclos (n+1))
1804 let args = Array.to_list arg in
1805 let all_args = args @ [clos] in
1807 if arity = 1 then app_fun clos 0 else
1809 Cop(Ccmpi Ceq, [get_field (Cvar clos) 1; int_const arity]),
1810 Cop(Capply(typ_addr, Debuginfo.none),
1811 get_field (Cvar clos) 2 :: List.map (fun s -> Cvar s) all_args),
1814 let send_function arity =
1815 let (args, clos', body) = apply_function_body (1+arity) in
1816 let cache = Ident.create "cache"
1817 and obj = List.hd args
1818 and tag = Ident.create "tag" in
1820 let cache = Cvar cache and obj = Cvar obj and tag = Cvar tag in
1821 let meths = Ident.create "meths" and cached = Ident.create "cached" in
1822 let real = Ident.create "real" in
1823 let mask = get_field (Cvar meths) 1 in
1824 let cached_pos = Cvar cached in
1825 let tag_pos = Cop(Cadda, [Cop (Cadda, [cached_pos; Cvar meths]);
1826 Cconst_int(3*size_addr-1)]) in
1827 let tag' = Cop(Cload Word, [tag_pos]) in
1829 meths, Cop(Cload Word, [obj]),
1831 cached, Cop(Cand, [Cop(Cload Word, [cache]); mask]),
1834 Cifthenelse(Cop(Ccmpa Cne, [tag'; tag]),
1835 cache_public_method (Cvar meths) tag cache,
1837 Cop(Cload Word, [Cop(Cadda, [Cop (Cadda, [Cvar real; Cvar meths]);
1838 Cconst_int(2*size_addr-1)])]))))
1841 let body = Clet(clos', clos, body) in
1843 [obj, typ_addr; tag, typ_int; cache, typ_addr]
1844 @ List.map (fun id -> (id, typ_addr)) (List.tl args) in
1846 {fun_name = "caml_send" ^ string_of_int arity;
1847 fun_args = fun_args;
1851 let apply_function arity =
1852 let (args, clos, body) = apply_function_body arity in
1853 let all_args = args @ [clos] in
1855 {fun_name = "caml_apply" ^ string_of_int arity;
1856 fun_args = List.map (fun id -> (id, typ_addr)) all_args;
1860 (* Generate tuplifying functions:
1861 (defun caml_tuplifyN (arg clos)
1862 (app clos.direct #0(arg) ... #N-1(arg) clos)) *)
1864 let tuplify_function arity =
1865 let arg = Ident.create "arg" in
1866 let clos = Ident.create "clos" in
1867 let rec access_components i =
1870 else get_field (Cvar arg) i :: access_components(i+1) in
1872 {fun_name = "caml_tuplify" ^ string_of_int arity;
1873 fun_args = [arg, typ_addr; clos, typ_addr];
1875 Cop(Capply(typ_addr, Debuginfo.none),
1876 get_field (Cvar clos) 2 :: access_components 0 @ [Cvar clos]);
1879 (* Generate currying functions:
1880 (defun caml_curryN (arg clos)
1881 (alloc HDR caml_curryN_1 arg clos))
1882 (defun caml_curryN_1 (arg clos)
1883 (alloc HDR caml_curryN_2 arg clos))
1885 (defun caml_curryN_N-1 (arg clos)
1886 (let (closN-2 clos.cdr
1892 clos1.car clos2.car ... closN-2.car clos.car arg clos))) *)
1894 let final_curry_function arity =
1895 let last_arg = Ident.create "arg" in
1896 let last_clos = Ident.create "clos" in
1897 let rec curry_fun args clos n =
1899 Cop(Capply(typ_addr, Debuginfo.none),
1900 get_field (Cvar clos) 2 ::
1901 args @ [Cvar last_arg; Cvar clos])
1903 let newclos = Ident.create "clos" in
1905 get_field (Cvar clos) 3,
1906 curry_fun (get_field (Cvar clos) 2 :: args) newclos (n-1))
1909 {fun_name = "caml_curry" ^ string_of_int arity ^
1910 "_" ^ string_of_int (arity-1);
1911 fun_args = [last_arg, typ_addr; last_clos, typ_addr];
1912 fun_body = curry_fun [] last_clos (arity-1);
1915 let rec intermediate_curry_functions arity num =
1916 if num = arity - 1 then
1917 [final_curry_function arity]
1919 let name1 = "caml_curry" ^ string_of_int arity in
1920 let name2 = if num = 0 then name1 else name1 ^ "_" ^ string_of_int num in
1921 let arg = Ident.create "arg" and clos = Ident.create "clos" in
1924 fun_args = [arg, typ_addr; clos, typ_addr];
1925 fun_body = Cop(Calloc,
1926 [alloc_closure_header 4;
1927 Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
1928 int_const 1; Cvar arg; Cvar clos]);
1930 :: intermediate_curry_functions arity (num+1)
1933 let curry_function arity =
1935 then intermediate_curry_functions arity 0
1936 else [tuplify_function (-arity)]
1939 module IntSet = Set.Make(
1942 let compare = compare
1945 let default_apply = IntSet.add 2 (IntSet.add 3 IntSet.empty)
1946 (* These apply funs are always present in the main program because
1947 the run-time system needs them (cf. asmrun/<arch>.S) . *)
1949 let generic_functions shared units =
1950 let (apply,send,curry) =
1952 (fun (apply,send,curry) ui ->
1953 List.fold_right IntSet.add ui.Compilenv.ui_apply_fun apply,
1954 List.fold_right IntSet.add ui.Compilenv.ui_send_fun send,
1955 List.fold_right IntSet.add ui.Compilenv.ui_curry_fun curry)
1956 (IntSet.empty,IntSet.empty,IntSet.empty)
1958 let apply = if shared then apply else IntSet.union apply default_apply in
1959 let accu = IntSet.fold (fun n accu -> apply_function n :: accu) apply [] in
1960 let accu = IntSet.fold (fun n accu -> send_function n :: accu) send accu in
1961 IntSet.fold (fun n accu -> curry_function n @ accu) curry accu
1963 (* Generate the entry point *)
1965 let entry_point namelist =
1966 let incr_global_inited =
1968 [Cconst_symbol "caml_globals_inited";
1969 Cop(Caddi, [Cop(Cload Word, [Cconst_symbol "caml_globals_inited"]);
1974 let entry_sym = Compilenv.make_symbol ~unitname:name (Some "entry") in
1975 Csequence(Cop(Capply(typ_void, Debuginfo.none),
1976 [Cconst_symbol entry_sym]),
1977 Csequence(incr_global_inited, next)))
1978 namelist (Cconst_int 1) in
1979 Cfunction {fun_name = "caml_program";
1984 (* Generate the table of globals *)
1986 let cint_zero = Cint 0n
1988 let global_table namelist =
1990 Csymbol_address (Compilenv.make_symbol ~unitname:name None)
1992 Cdata(Cglobal_symbol "caml_globals" ::
1993 Cdefine_symbol "caml_globals" ::
1994 List.map mksym namelist @
1997 let reference_symbols namelist =
1998 let mksym name = Csymbol_address name in
1999 Cdata(List.map mksym namelist)
2001 let global_data name v =
2002 Cdata(Cglobal_symbol name ::
2004 (Const_base (Const_string (Marshal.to_string v []))) [])
2006 let globals_map v = global_data "caml_globals_map" v
2008 (* Generate the master table of frame descriptors *)
2010 let frame_table namelist =
2012 Csymbol_address (Compilenv.make_symbol ~unitname:name (Some "frametable"))
2014 Cdata(Cglobal_symbol "caml_frametable" ::
2015 Cdefine_symbol "caml_frametable" ::
2016 List.map mksym namelist
2019 (* Generate the table of module data and code segments *)
2021 let segment_table namelist symbol begname endname =
2022 let addsyms name lst =
2023 Csymbol_address (Compilenv.make_symbol ~unitname:name (Some begname)) ::
2024 Csymbol_address (Compilenv.make_symbol ~unitname:name (Some endname)) ::
2027 Cdata(Cglobal_symbol symbol ::
2028 Cdefine_symbol symbol ::
2029 List.fold_right addsyms namelist [cint_zero])
2031 let data_segment_table namelist =
2032 segment_table namelist "caml_data_segments" "data_begin" "data_end"
2034 let code_segment_table namelist =
2035 segment_table namelist "caml_code_segments" "code_begin" "code_end"
2037 (* Initialize a predefined exception *)
2039 let predef_exception name =
2040 let bucketname = "caml_bucket_" ^ name in
2041 let symname = "caml_exn_" ^ name in
2042 Cdata(Cglobal_symbol symname ::
2043 emit_constant symname (Const_block(0,[Const_base(Const_string name)]))
2044 [ Cglobal_symbol bucketname;
2045 Cint(block_header 0 1);
2046 Cdefine_symbol bucketname;
2047 Csymbol_address symname ])
2049 (* Header for a plugin *)
2051 let mapflat f l = List.flatten (List.map f l)
2056 imports_cmi: (string * Digest.t) list;
2057 imports_cmx: (string * Digest.t) list;
2058 defines: string list;
2063 units: dynunit list;
2066 let dyn_magic_number = "Caml2007D001"
2068 let plugin_header units =
2070 { name = ui.Compilenv.ui_name;
2072 imports_cmi = ui.Compilenv.ui_imports_cmi;
2073 imports_cmx = ui.Compilenv.ui_imports_cmx;
2074 defines = ui.Compilenv.ui_defines
2076 global_data "caml_plugin_header"
2077 { magic = dyn_magic_number; units = List.map mk units }