Skip to content

Commit d35d125

Browse files
Ekdohibslthls
andauthored
flambda-backend: Propagate never-returning functions, except when annotated with [@opaque] (#2099)
* Propagate never-returning functions, except when annotated with [@opaque] * fix backtrace tests * Remove redundant `[@@inline never]` Co-authored-by: Vincent Laviron <[email protected]> --------- Co-authored-by: Vincent Laviron <[email protected]>
1 parent 37317bb commit d35d125

File tree

7 files changed

+68
-3
lines changed

7 files changed

+68
-3
lines changed

lambda/lambda.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ type function_attribute = {
569569
poll: poll_attribute;
570570
loop: loop_attribute;
571571
is_a_functor: bool;
572+
is_opaque: bool;
572573
stub: bool;
573574
tmc_candidate: bool;
574575
}
@@ -758,6 +759,7 @@ let default_function_attribute = {
758759
poll = Default_poll;
759760
loop = Default_loop;
760761
is_a_functor = false;
762+
is_opaque = false;
761763
stub = false;
762764
tmc_candidate = false;
763765
}

lambda/lambda.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ type function_attribute = {
465465
poll: poll_attribute;
466466
loop: loop_attribute;
467467
is_a_functor: bool;
468+
is_opaque: bool;
468469
stub: bool;
469470
tmc_candidate: bool;
470471
}

lambda/translattribute.ml

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ let is_poll_attribute =
5050
let is_loop_attribute =
5151
[ ["loop"; "ocaml.loop"], true ]
5252

53+
let is_opaque_attribute =
54+
[ ["opaque"; "ocaml.opaque"], true ]
55+
56+
5357
let find_attribute p attributes =
5458
let inline_attribute =
5559
Builtin_attributes.filter_attributes
@@ -297,6 +301,17 @@ let parse_loop_attribute attr =
297301
]
298302
payload
299303

304+
let parse_opaque_attribute attr =
305+
match attr with
306+
| None -> false
307+
| Some {Parsetree.attr_name = {txt; loc}; attr_payload = payload} ->
308+
parse_id_payload txt loc
309+
~default:false
310+
~empty:true
311+
[]
312+
payload
313+
314+
300315
let get_inline_attribute l =
301316
let attr = find_attribute is_inline_attribute l in
302317
parse_inline_attribute attr
@@ -309,6 +324,11 @@ let get_local_attribute l =
309324
let attr = find_attribute is_local_attribute l in
310325
parse_local_attribute attr
311326

327+
let get_opaque_attribute l =
328+
let attr = find_attribute is_opaque_attribute l in
329+
parse_opaque_attribute attr
330+
331+
312332
let get_property_attribute l p =
313333
let attr = find_attribute (is_property_attribute p) l in
314334
let res = parse_property_attribute attr p in
@@ -360,6 +380,25 @@ let check_poll_local loc attr =
360380
| _ ->
361381
()
362382

383+
let check_opaque_inline loc attr =
384+
match attr.is_opaque, attr.inline with
385+
| true, (Always_inline | Available_inline | Unroll _) ->
386+
Location.prerr_warning loc
387+
(Warnings.Inlining_impossible
388+
"[@opaque] is incompatible with inlining")
389+
| _ ->
390+
()
391+
392+
let check_opaque_local loc attr =
393+
match attr.is_opaque, attr.local with
394+
| true, Always_local ->
395+
Location.prerr_warning loc
396+
(Warnings.Inlining_impossible
397+
"[@opaque] is incompatible with local function optimization")
398+
| _ ->
399+
()
400+
401+
363402
let lfunction_with_attr ~attr
364403
{ kind; params; return; body; attr=_; loc; mode; ret_mode; region } =
365404
lfunction ~kind ~params ~return ~body ~attr ~loc ~mode ~ret_mode ~region
@@ -525,6 +564,24 @@ let add_poll_attribute expr loc attributes =
525564
end
526565
| expr -> expr
527566

567+
let add_opaque_attribute expr loc attributes =
568+
match expr with
569+
| Lfunction({ attr } as funct) ->
570+
if not (get_opaque_attribute attributes) then
571+
expr
572+
else begin
573+
if attr.is_opaque then
574+
Location.prerr_warning loc
575+
(Warnings.Duplicated_attribute "opaque");
576+
let attr = { attr with is_opaque = true } in
577+
check_opaque_inline loc attr;
578+
check_opaque_local loc attr;
579+
let attr = { attr with inline = Never_inline; local = Never_local } in
580+
lfunction_with_attr ~attr funct
581+
end
582+
| _ -> expr
583+
584+
528585
(* Get the [@inlined] attribute payload (or default if not present). *)
529586
let get_inlined_attribute e =
530587
let attr = find_attribute is_inlined_attribute e.exp_attributes in
@@ -584,8 +641,11 @@ let add_function_attributes lam loc attr =
584641
let lam =
585642
add_tmc_attribute lam loc attr
586643
in
644+
(* last because poll and opaque overrides inline and local *)
587645
let lam =
588-
(* last because poll overrides inline and local *)
589646
add_poll_attribute lam loc attr
590647
in
648+
let lam =
649+
add_opaque_attribute lam loc attr
650+
in
591651
lam

lambda/translcore.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,7 @@ and transl_exp0 ~in_new_scope ~scopes sort e =
955955
check = Default_check;
956956
loop = Never_loop;
957957
is_a_functor = false;
958+
is_opaque = false;
958959
stub = false;
959960
poll = Default_poll;
960961
tmc_candidate = false;

lambda/translmod.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ let rec compile_functor ~scopes mexp coercion root_path loc =
598598
poll = Default_poll;
599599
loop = Never_loop;
600600
is_a_functor = true;
601+
is_opaque = false;
601602
check = Ignore_assert_all Zero_alloc;
602603
stub = false;
603604
tmc_candidate = false;

testsuite/tests/backtrace/pr6920_why_at.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
exit_status = "2"
66
*)
77

8-
let why : unit -> unit = fun () -> raise Exit [@@inline never]
8+
let why : unit -> unit = fun () -> raise Exit [@@opaque]
99
let f () =
1010
why @@ ();
1111
ignore (3 + 2);

testsuite/tests/backtrace/pr6920_why_swallow.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
exit_status = "2"
66
*)
77

8-
let why : unit -> unit = fun () -> raise Exit [@@inline never]
8+
let why : unit -> unit = fun () -> raise Exit [@@opaque]
99
let f () =
1010
for i = 1 to 10 do
1111
why @@ ();

0 commit comments

Comments
 (0)