Skip to content

Commit f8dae64

Browse files
authored
flambda-backend: Add region in Call_kind for C calls (#2180)
1 parent 341437c commit f8dae64

File tree

5 files changed

+50
-6
lines changed

5 files changed

+50
-6
lines changed

lambda/lambda.ml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,25 @@ let mod_field ?(read_semantics=Reads_agree) pos =
14431443
let mod_setfield pos =
14441444
Psetfield (pos, Pointer, Root_initialization)
14451445

1446+
let alloc_mode_of_primitive_description (p : Primitive.description) =
1447+
if not Config.stack_allocation then
1448+
if p.prim_alloc then Some alloc_heap else None
1449+
else
1450+
match p.prim_native_repr_res with
1451+
| (Prim_local | Prim_poly), _ ->
1452+
(* For primitives that might allocate locally, [p.prim_alloc] just says
1453+
whether [caml_c_call] is required, without telling us anything
1454+
about local allocation. (However if [p.prim_alloc = false] we
1455+
do actually know that the primitive does not allocate on the heap.) *)
1456+
Some alloc_local
1457+
| Prim_global, _ ->
1458+
(* For primitives that definitely do not allocate locally,
1459+
[p.prim_alloc = false] actually tells us that the primitive does
1460+
not allocate at all. *)
1461+
if p.prim_alloc then Some alloc_heap else None
1462+
1463+
(* Changes to this function may also require changes in Flambda 2 (e.g.
1464+
closure_conversion.ml). *)
14461465
let primitive_may_allocate : primitive -> alloc_mode option = function
14471466
| Pbytes_to_string | Pbytes_of_string
14481467
| Parray_to_iarray | Parray_of_iarray
@@ -1458,12 +1477,7 @@ let primitive_may_allocate : primitive -> alloc_mode option = function
14581477
| Psetufloatfield _ -> None
14591478
| Pduprecord _ -> Some alloc_heap
14601479
| Pmake_unboxed_product _ | Punboxed_product_field _ -> None
1461-
| Pccall p ->
1462-
if not p.prim_alloc then None
1463-
else begin match p.prim_native_repr_res with
1464-
| (Prim_local|Prim_poly), _ -> Some alloc_local
1465-
| Prim_global, _ -> Some alloc_heap
1466-
end
1480+
| Pccall p -> alloc_mode_of_primitive_description p
14671481
| Praise _ -> None
14681482
| Psequor | Psequand | Pnot
14691483
| Pnegint | Paddint | Psubint | Pmulint

lambda/lambda.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,10 @@ val primitive_may_allocate : primitive -> alloc_mode option
752752
revised.
753753
*)
754754

755+
val alloc_mode_of_primitive_description :
756+
Primitive.description -> alloc_mode option
757+
(** Like [primitive_may_allocate], for [external] calls. *)
758+
755759
(***********************)
756760
(* For static failures *)
757761
(***********************)

testsuite/tests/typing-local/alloc.heap.reference

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
longarray: Allocation
2424
floatgenarray: Allocation
2525
longfgarray: Allocation
26+
maniparray0: Allocation
2627
maniparray: Allocation
2728
manipfarray: Allocation
2829
ref: Allocation

testsuite/tests/typing-local/alloc.ml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@
99
reference = "${test_source_directory}/alloc.heap.reference"
1010
*)
1111

12+
(* First test to ensure that noalloc externals that locally allocate
13+
don't cause a crash in the middle end (originally seen on
14+
flambda-backend PR2180). *)
15+
16+
(* This will never be called, caml_alloc_dummy is just chosen as a primitive that
17+
exists in the bytecode runtime too *)
18+
external foo : unit -> ('a[@local_opt]) =
19+
"caml_alloc_dummy" "caml_alloc_dummy" [@@noalloc]
20+
21+
let foo () = foo ()
22+
23+
(* Remaining tests *)
24+
1225
type t = int
1326

1427
type smallrecord = { a : t; b : t; c : t }
@@ -264,6 +277,16 @@ external array_blit :
264277
external array_fill :
265278
local_ 'a array -> int -> int -> 'a -> unit = "caml_array_fill"
266279

280+
let maniparray0 =
281+
let l = [42] in
282+
fun arr ->
283+
(* This function should only locally allocate in the C runtime function
284+
for doing the array allocation, and not in the OCaml code, in order
285+
to ensure that locally-allocating C calls hold onto regions. *)
286+
let x = local_array 6 l in
287+
assert (x = arr);
288+
()
289+
267290
let maniparray arr = (* arr = 1,2,3,1,2,3 *)
268291
let x = local_array 2 [2] in (* 2,2 *)
269292
let x = array_append x x in (* 2,2,2,2 *)
@@ -472,6 +495,7 @@ let () =
472495
run "longarray" makelongarray 42;
473496
run "floatgenarray" makeshortarray 42.;
474497
run "longfgarray" makelongarray 42.;
498+
run "maniparray0" maniparray0 [| [42]; [42]; [42]; [42]; [42]; [42] |];
475499
run "maniparray" maniparray [| [1]; [2]; [3]; [1]; [2]; [3] |];
476500
run "manipfarray" manipfarray [| 1.; 2.; 3.; 1.; 2.; 3. |];
477501
run "ref" makeref 42;

testsuite/tests/typing-local/alloc.stack.reference

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
longarray: No Allocation
2424
floatgenarray: No Allocation
2525
longfgarray: No Allocation
26+
maniparray0: No Allocation
2627
maniparray: No Allocation
2728
manipfarray: No Allocation
2829
ref: No Allocation

0 commit comments

Comments
 (0)