Skip to content

Treat Prim_poly primitives as Alloc_heap in Lambda #2190

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions ocaml/lambda/lambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1445,16 +1445,19 @@ let alloc_mode_of_primitive_description (p : Primitive.description) =
if p.prim_alloc then Some alloc_heap else None
else
match p.prim_native_repr_res with
| (Prim_local | Prim_poly), _ ->
| Prim_local, _ ->
(* For primitives that might allocate locally, [p.prim_alloc] just says
whether [caml_c_call] is required, without telling us anything
about local allocation. (However if [p.prim_alloc = false] we
do actually know that the primitive does not allocate on the heap.) *)
Some alloc_local
| Prim_global, _ ->
| (Prim_global | Prim_poly), _ ->
(* For primitives that definitely do not allocate locally,
[p.prim_alloc = false] actually tells us that the primitive does
not allocate at all. *)
not allocate at all.

No external call that is [Prim_poly] may allocate locally.
*)
if p.prim_alloc then Some alloc_heap else None

(* Changes to this function may also require changes in Flambda 2 (e.g.
Expand Down
36 changes: 21 additions & 15 deletions ocaml/lambda/printlambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,15 @@ let array_set_kind ppf k =
| Pintarray_set -> fprintf ppf "int"
| Pfloatarray_set -> fprintf ppf "float"

let alloc_mode = function
let alloc_mode_if_local = function
| Alloc_heap -> ""
| Alloc_local -> "local"

let alloc_mode ppf alloc_mode =
match alloc_mode with
| Alloc_heap -> fprintf ppf "heap"
| Alloc_local -> fprintf ppf "local"

let boxed_integer_name = function
| Pnativeint -> "nativeint"
| Pint32 -> "int32"
Expand Down Expand Up @@ -143,7 +148,7 @@ let rec layout is_top ppf layout_ =
let layout ppf layout_ = layout true ppf layout_

let return_kind ppf (mode, kind) =
let smode = alloc_mode mode in
let smode = alloc_mode_if_local mode in
match kind with
| Pvalue Pgenval when is_heap_mode mode -> ()
| Pvalue Pgenval -> fprintf ppf ": %s@ " smode
Expand Down Expand Up @@ -275,31 +280,31 @@ let primitive ppf = function
| Pgetpredef id -> fprintf ppf "getpredef %a!" Ident.print id
| Pmakeblock(tag, Immutable, shape, mode) ->
fprintf ppf "make%sblock %i%a"
(alloc_mode mode) tag block_shape shape
(alloc_mode_if_local mode) tag block_shape shape
| Pmakeblock(tag, Immutable_unique, shape, mode) ->
fprintf ppf "make%sblock_unique %i%a"
(alloc_mode mode) tag block_shape shape
(alloc_mode_if_local mode) tag block_shape shape
| Pmakeblock(tag, Mutable, shape, mode) ->
fprintf ppf "make%smutable %i%a"
(alloc_mode mode) tag block_shape shape
(alloc_mode_if_local mode) tag block_shape shape
| Pmakefloatblock (Immutable, mode) ->
fprintf ppf "make%sfloatblock Immutable"
(alloc_mode mode)
(alloc_mode_if_local mode)
| Pmakefloatblock (Immutable_unique, mode) ->
fprintf ppf "make%sfloatblock Immutable_unique"
(alloc_mode mode)
(alloc_mode_if_local mode)
| Pmakefloatblock (Mutable, mode) ->
fprintf ppf "make%sfloatblock Mutable"
(alloc_mode mode)
(alloc_mode_if_local mode)
| Pmakeufloatblock (Immutable, mode) ->
fprintf ppf "make%sufloatblock Immutable"
(alloc_mode mode)
(alloc_mode_if_local mode)
| Pmakeufloatblock (Immutable_unique, mode) ->
fprintf ppf "make%sufloatblock Immutable_unique"
(alloc_mode mode)
(alloc_mode_if_local mode)
| Pmakeufloatblock (Mutable, mode) ->
fprintf ppf "make%sufloatblock Mutable"
(alloc_mode mode)
(alloc_mode_if_local mode)
| Pfield (n, ptr, sem) ->
let instr =
match ptr, sem with
Expand Down Expand Up @@ -340,7 +345,7 @@ let primitive ppf = function
fprintf ppf "setfield_%s%s_computed" instr init
| Pfloatfield (n, sem, mode) ->
fprintf ppf "floatfield%a%s %i"
field_read_semantics sem (alloc_mode mode) n
field_read_semantics sem (alloc_mode_if_local mode) n
| Pufloatfield (n, sem) ->
fprintf ppf "ufloatfield%a %i"
field_read_semantics sem n
Expand Down Expand Up @@ -419,11 +424,12 @@ let primitive ppf = function

| Parraylength k -> fprintf ppf "array.length[%s]" (array_kind k)
| Pmakearray (k, Mutable, mode) ->
fprintf ppf "make%sarray[%s]" (alloc_mode mode) (array_kind k)
fprintf ppf "make%sarray[%s]" (alloc_mode_if_local mode) (array_kind k)
| Pmakearray (k, Immutable, mode) ->
fprintf ppf "make%sarray_imm[%s]" (alloc_mode mode) (array_kind k)
fprintf ppf "make%sarray_imm[%s]" (alloc_mode_if_local mode) (array_kind k)
| Pmakearray (k, Immutable_unique, mode) ->
fprintf ppf "make%sarray_unique[%s]" (alloc_mode mode) (array_kind k)
fprintf ppf "make%sarray_unique[%s]" (alloc_mode_if_local mode)
(array_kind k)
| Pduparray (k, Mutable) -> fprintf ppf "duparray[%s]" (array_kind k)
| Pduparray (k, Immutable) -> fprintf ppf "duparray_imm[%s]" (array_kind k)
| Pduparray (k, Immutable_unique) ->
Expand Down
1 change: 1 addition & 0 deletions ocaml/lambda/printlambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ val print_bigarray :
string -> bool -> Lambda.bigarray_kind -> formatter ->
Lambda.bigarray_layout -> unit
val check_attribute : formatter -> check_attribute -> unit
val alloc_mode : formatter -> alloc_mode -> unit
42 changes: 40 additions & 2 deletions ocaml/lambda/translprim.ml
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,11 @@ let lambda_of_prim prim_name prim loc args arg_exps =
let check_primitive_arity loc p =
let mode =
match p.prim_native_repr_res with
| Prim_global, _ | Prim_poly, _ -> Some Mode.Locality.global
| Prim_global, _ | Prim_poly, _ ->
(* We assume all primitives are compiled to have the same arity for
different modes and types, so just pick one of the modes in the
[Prim_poly] case. *)
Some Mode.Locality.global
| Prim_local, _ -> Some Mode.Locality.local
in
let prim = lookup_primitive loc mode Rc_normal p in
Expand Down Expand Up @@ -981,8 +985,42 @@ let transl_primitive loc p env ty ~poly_mode path =
loc
in
let body = lambda_of_prim p.prim_name prim loc args None in
let alloc_mode = to_locality p.prim_native_repr_res in
let () =
(* CR mshinwell: Write a version of [primitive_may_allocate] that
works on the [prim] type. *)
match body with
| Lprim (prim, _, _) ->
(match Lambda.primitive_may_allocate prim with
| None ->
(* We don't check anything in this case; if the primitive doesn't
allocate, then after [Lambda] it will be translated to a term
not involving any region variables, meaning there would be
no concern about potentially unbound region variables. *)
()
| Some lambda_alloc_mode ->
(* In this case we add a check to ensure the middle end has
the correct information as to whether a region was inserted
at this point. *)
match alloc_mode, lambda_alloc_mode with
| Alloc_heap, Alloc_heap
| Alloc_local, Alloc_local -> ()
| Alloc_local, Alloc_heap ->
(* This case is ok: the Lambda-derived information is more
precise. A region will be inserted, likely unused, and
deleted by the middle end. *)
()
| Alloc_heap, Alloc_local ->
Misc.fatal_errorf "Alloc mode incompatibility for:@ %a@ \
(from to_locality, %a; from primitive_may_allocate, %a)"
Printlambda.lambda body
Printlambda.alloc_mode alloc_mode
Printlambda.alloc_mode lambda_alloc_mode
)
| _ -> ()
in
let region =
match to_locality p.prim_native_repr_res with
match alloc_mode with
| Alloc_heap -> true
| Alloc_local -> false
in
Expand Down
19 changes: 19 additions & 0 deletions ocaml/testsuite/tests/typing-local/external.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(* TEST
* flambda2
** native
*)

module M : sig
val bits_of_float : float -> int64
end = struct
external bits_of_float
: (float[@local_opt])
-> (int64[@local_opt])
= "caml_int64_bits_of_float" "caml_int64_bits_of_float_unboxed"
[@@unboxed] [@@noalloc]
end

let go_m f =
let i = M.bits_of_float f in
assert (i = 4L);
()