Skip to content

Commit

Permalink
flambda-backend: Properly handle regions around recursive definitions (
Browse files Browse the repository at this point in the history
…#2601)

* Properly handle regions around recursive definitions

* Update tests: add reference output and original minimal example
  • Loading branch information
lthls authored May 22, 2024
1 parent 3956aa4 commit a686de9
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 1 deletion.
10 changes: 9 additions & 1 deletion lambda/value_rec_compiler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,15 @@ let rec split_static_function lfun block_var local_idents lam :
| Levent (lam, lev) ->
let+ lam = split_static_function lfun block_var local_idents lam in
Levent (lam, lev)
| Lregion (lam, layout_fun) ->
(* The type-checker forbids recursive values from being allocated on the
stack, so this region is only here to collect temporary allocations.
In particular the function itself does not capture any stack-allocated
variables, so we can lift it out of the region. *)
let+ lam = split_static_function lfun block_var local_idents lam in
(* The new expression returns the closure block instead of the function *)
ignore layout_fun;
Lregion (lam, layout_block)
| Lmutvar _
| Lconst _
| Lapply _
Expand All @@ -671,7 +680,6 @@ let rec split_static_function lfun block_var local_idents lam :
| Lassign _
| Lsend _
| Lifused _
| Lregion _
| Lexclave _ ->
Misc.fatal_errorf
"letrec binding is not a static function:@ lfun=%a@ lam=%a"
Expand Down
19 changes: 19 additions & 0 deletions testsuite/tests/letrec-compilation/region.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(* TEST *)

(* Recursive values are not allowed to be stack-allocated, but their
defining expressions are allowed to make allocations on the stack.
This can introduce a region around the whole definition. *)

let rec f =
let p = local_ (fun msg -> print_string msg) in
p "hello, ";
p "world!";
print_newline ();
fun x -> f x

(* Original bug report: unused function *)
let rec foo =
let _f x = x, foo in
function
| None -> foo None
| Some x -> x
1 change: 1 addition & 0 deletions testsuite/tests/letrec-compilation/region.reference
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello, world!

0 comments on commit a686de9

Please sign in to comment.