Skip to content

Commit 79c9bbf

Browse files
committed
Treat Prim_poly primitives as Alloc_heap in Lambda
1 parent e88456b commit 79c9bbf

File tree

5 files changed

+69
-5
lines changed

5 files changed

+69
-5
lines changed

ocaml/lambda/lambda.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,16 +1445,19 @@ let alloc_mode_of_primitive_description (p : Primitive.description) =
14451445
if p.prim_alloc then Some alloc_heap else None
14461446
else
14471447
match p.prim_native_repr_res with
1448-
| (Prim_local | Prim_poly), _ ->
1448+
| Prim_local, _ ->
14491449
(* For primitives that might allocate locally, [p.prim_alloc] just says
14501450
whether [caml_c_call] is required, without telling us anything
14511451
about local allocation. (However if [p.prim_alloc = false] we
14521452
do actually know that the primitive does not allocate on the heap.) *)
14531453
Some alloc_local
1454-
| Prim_global, _ ->
1454+
| (Prim_global | Prim_poly), _ ->
14551455
(* For primitives that definitely do not allocate locally,
14561456
[p.prim_alloc = false] actually tells us that the primitive does
1457-
not allocate at all. *)
1457+
not allocate at all.
1458+
1459+
No external call that is [Prim_poly] may allocate locally.
1460+
*)
14581461
if p.prim_alloc then Some alloc_heap else None
14591462

14601463
(* Changes to this function may also require changes in Flambda 2 (e.g.

ocaml/lambda/printlambda.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ let alloc_mode = function
8888
| Alloc_heap -> ""
8989
| Alloc_local -> "local"
9090

91+
let alloc_mode' = function
92+
| Alloc_heap -> "heap"
93+
| Alloc_local -> "local"
94+
9195
let boxed_integer_name = function
9296
| Pnativeint -> "nativeint"
9397
| Pint32 -> "int32"

ocaml/lambda/printlambda.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ val print_bigarray :
3636
string -> bool -> Lambda.bigarray_kind -> formatter ->
3737
Lambda.bigarray_layout -> unit
3838
val check_attribute : formatter -> check_attribute -> unit
39+
val alloc_mode' : alloc_mode -> string

ocaml/lambda/translprim.ml

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,11 @@ let lambda_of_prim prim_name prim loc args arg_exps =
909909
let check_primitive_arity loc p =
910910
let mode =
911911
match p.prim_native_repr_res with
912-
| Prim_global, _ | Prim_poly, _ -> Some Mode.Locality.global
912+
| Prim_global, _ | Prim_poly, _ ->
913+
(* We assume all primitives are compiled to have the same arity for
914+
different modes and types, so just pick one of the modes in the
915+
[Prim_poly] case. *)
916+
Some Mode.Locality.global
913917
| Prim_local, _ -> Some Mode.Locality.local
914918
in
915919
let prim = lookup_primitive loc mode Rc_normal p in
@@ -981,8 +985,42 @@ let transl_primitive loc p env ty ~poly_mode path =
981985
loc
982986
in
983987
let body = lambda_of_prim p.prim_name prim loc args None in
988+
let alloc_mode = to_locality p.prim_native_repr_res in
989+
let () =
990+
(* CR mshinwell: Write a version of [primitive_may_allocate] that
991+
works on the [prim] type. *)
992+
match body with
993+
| Lprim (prim, _, _) ->
994+
(match Lambda.primitive_may_allocate prim with
995+
| None ->
996+
(* We don't check anything in this case; if the primitive doesn't
997+
allocate, then after [Lambda] it will be translated to a term
998+
not involving any region variables, meaning there would be
999+
no concern about potentially unbound region variables. *)
1000+
()
1001+
| Some lambda_alloc_mode ->
1002+
(* In this case we add a check to ensure the middle end has
1003+
the correct information as to whether a region was inserted
1004+
at this point. *)
1005+
match alloc_mode, lambda_alloc_mode with
1006+
| Alloc_heap, Alloc_heap
1007+
| Alloc_local, Alloc_local -> ()
1008+
| Alloc_local, Alloc_heap ->
1009+
(* This case is ok: the Lambda-derived information is more
1010+
precise. A region will be inserted, likely unused, and
1011+
deleted by the middle end. *)
1012+
()
1013+
| Alloc_heap, Alloc_local ->
1014+
Misc.fatal_errorf "Alloc mode incompatibility for:@ %a@ \
1015+
(from to_locality, %s; from primitive_may_allocate, %s)"
1016+
Printlambda.lambda body
1017+
(Printlambda.alloc_mode' alloc_mode)
1018+
(Printlambda.alloc_mode' lambda_alloc_mode)
1019+
)
1020+
| _ -> ()
1021+
in
9841022
let region =
985-
match to_locality p.prim_native_repr_res with
1023+
match alloc_mode with
9861024
| Alloc_heap -> true
9871025
| Alloc_local -> false
9881026
in
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
(* TEST
2+
* flambda2
3+
** native
4+
*)
5+
6+
module M : sig
7+
val bits_of_float : float -> int64
8+
end = struct
9+
external bits_of_float
10+
: (float[@local_opt])
11+
-> (int64[@local_opt])
12+
= "caml_int64_bits_of_float" "caml_int64_bits_of_float_unboxed"
13+
end
14+
15+
let go_m f =
16+
let i = M.bits_of_float f in
17+
assert (i = 4L);
18+
()

0 commit comments

Comments
 (0)