Skip to content

Commit 23a7f73

Browse files
mshinwellpoechsel
andauthored
flambda-backend: Fix some Debuginfo.t scopes in the frontend (#248)
* Add Debuginfo scopes for partial/eta expansion wrappers and "lazy"; use in the frontend. * Fix test As bytecode and native differs in how they handle partial application the check for partial applications has been split in a new separate testcase. Co-authored-by: Pierre Oechsel <[email protected]>
1 parent 33a04a6 commit 23a7f73

File tree

10 files changed

+122
-49
lines changed

10 files changed

+122
-49
lines changed

lambda/debuginfo.ml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,17 @@ module Scoped_location = struct
2424
| Sc_module_definition
2525
| Sc_class_definition
2626
| Sc_method_definition
27+
| Sc_partial_or_eta_wrapper
28+
| Sc_lazy
2729

2830
type scopes =
2931
| Empty
3032
| Cons of {item: scope_item; str: string; str_fun: string}
3133

34+
let str = function
35+
| Empty -> ""
36+
| Cons r -> r.str
37+
3238
let str_fun = function
3339
| Empty -> "(fun)"
3440
| Cons r -> r.str_fun
@@ -45,8 +51,12 @@ module Scoped_location = struct
4551
| 'a'..'z' | 'A'..'Z' | '_' | '0'..'9' -> s
4652
| _ -> "(" ^ s ^ ")"
4753

48-
let dot ?(sep = ".") scopes s =
49-
let s = add_parens_if_symbolic s in
54+
let dot ?(sep = ".") ?no_parens scopes s =
55+
let s =
56+
match no_parens with
57+
| None -> add_parens_if_symbolic s
58+
| Some () -> s
59+
in
5060
match scopes with
5161
| Empty -> s
5262
| Cons {str; _} -> str ^ sep ^ s
@@ -72,6 +82,11 @@ module Scoped_location = struct
7282
in
7383
cons Sc_method_definition str
7484

85+
let enter_lazy ~scopes = cons Sc_lazy (str scopes)
86+
87+
let enter_partial_or_eta_wrapper ~scopes =
88+
cons Sc_partial_or_eta_wrapper (dot ~no_parens:() scopes "(partial)")
89+
7590
let string_of_scopes = function
7691
| Empty -> "<unknown>"
7792
| Cons {str; _} -> str
@@ -106,6 +121,11 @@ module Scoped_location = struct
106121
let string_of_scoped_location = function
107122
| Loc_unknown -> "??"
108123
| Loc_known { loc = _; scopes } -> string_of_scopes scopes
124+
125+
let map_scopes f t =
126+
match t with
127+
| Loc_unknown -> Loc_unknown
128+
| Loc_known { loc; scopes } -> Loc_known { loc; scopes = f ~scopes }
109129
end
110130

111131
type item = {

lambda/debuginfo.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ module Scoped_location : sig
2323
val enter_module_definition : scopes:scopes -> Ident.t -> scopes
2424
val enter_class_definition : scopes:scopes -> Ident.t -> scopes
2525
val enter_method_definition : scopes:scopes -> Asttypes.label -> scopes
26+
val enter_lazy : scopes:scopes -> scopes
27+
val enter_partial_or_eta_wrapper : scopes:scopes -> scopes
2628

2729
type t =
2830
| Loc_unknown
@@ -33,6 +35,8 @@ module Scoped_location : sig
3335
val of_location : scopes:scopes -> Location.t -> t
3436
val to_location : t -> Location.t
3537
val string_of_scoped_location : t -> string
38+
39+
val map_scopes : (scopes:scopes -> scopes) -> t -> t
3640
end
3741

3842
type item = private {

lambda/translcore.ml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ and transl_exp0 ~in_new_scope ~scopes e =
593593
transl_exp ~scopes e
594594
| `Other ->
595595
(* other cases compile to a lazy block holding a function *)
596+
let scopes = enter_lazy ~scopes in
596597
let fn = Lfunction {kind = Curried;
597598
params= [Ident.create_local "param", Pgenval];
598599
return = Pgenval;
@@ -755,7 +756,7 @@ and transl_apply ~scopes
755756
?(specialised = Default_specialise)
756757
lam sargs loc
757758
=
758-
let lapply funct args =
759+
let lapply loc funct args =
759760
match funct with
760761
Lsend(k, lmet, lobj, largs, _) ->
761762
Lsend(k, lmet, lobj, largs @ args, loc)
@@ -774,7 +775,7 @@ and transl_apply ~scopes
774775
ap_probe=None;
775776
}
776777
in
777-
let rec build_apply lam args = function
778+
let rec build_apply lam args loc = function
778779
(None, optional) :: l ->
779780
let defs = ref [] in
780781
let protect name lam =
@@ -790,15 +791,16 @@ and transl_apply ~scopes
790791
else args, []
791792
in
792793
let lam =
793-
if args = [] then lam else lapply lam (List.rev_map fst args)
794+
if args = [] then lam else lapply loc lam (List.rev_map fst args)
794795
in
795796
let handle = protect "func" lam in
796797
let l =
797798
List.map (fun (arg, opt) -> Option.map (protect "arg") arg, opt) l
798799
in
799800
let id_arg = Ident.create_local "param" in
800801
let body =
801-
match build_apply handle ((Lvar id_arg, optional)::args') l with
802+
let loc = map_scopes enter_partial_or_eta_wrapper loc in
803+
match build_apply handle ((Lvar id_arg, optional)::args') loc l with
802804
Lfunction{kind = Curried; params = ids; return;
803805
body = lam; attr; loc}
804806
when List.length ids < Lambda.max_arity () ->
@@ -822,11 +824,11 @@ and transl_apply ~scopes
822824
(fun body (id, lam) -> Llet(Strict, Pgenval, id, lam, body))
823825
body !defs
824826
| (Some arg, optional) :: l ->
825-
build_apply lam ((arg, optional) :: args) l
827+
build_apply lam ((arg, optional) :: args) loc l
826828
| [] ->
827-
lapply lam (List.rev_map fst args)
829+
lapply loc lam (List.rev_map fst args)
828830
in
829-
(build_apply lam [] (List.map (fun (l, x) ->
831+
(build_apply lam [] loc (List.map (fun (l, x) ->
830832
Option.map (transl_exp ~scopes) x,
831833
Btype.is_optional l)
832834
sargs)

lambda/translprim.ml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -732,16 +732,21 @@ let transl_primitive loc p env ty path =
732732
in
733733
let params = make_params p.prim_arity in
734734
let args = List.map (fun (id, _) -> Lvar id) params in
735+
let loc =
736+
Debuginfo.Scoped_location.map_scopes (fun ~scopes ->
737+
Debuginfo.Scoped_location.enter_partial_or_eta_wrapper ~scopes)
738+
loc
739+
in
735740
let body = lambda_of_prim p.prim_name prim loc args None in
736741
match params with
737742
| [] -> body
738743
| _ ->
739-
Lfunction{ kind = Curried;
740-
params;
741-
return = Pgenval;
742-
attr = default_stub_attribute;
743-
loc;
744-
body; }
744+
Lfunction{ kind = Curried;
745+
params;
746+
return = Pgenval;
747+
attr = default_stub_attribute;
748+
loc;
749+
body; }
745750

746751
let lambda_primitive_needs_event_after = function
747752
| Prevapply | Pdirapply (* PR#6920 *)

testsuite/tests/backtrace/names.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
(* TEST
22
flags = "-g"
3+
34
*)
45

56

67
let id x = Sys.opaque_identity x
78

89
let[@inline never] bang () = raise Exit
910

10-
1111
let[@inline never] fn_multi _ _ f = f 42 + 1
1212

1313
let[@inline never] fn_function = function
@@ -97,6 +97,10 @@ let inline_object f =
9797
end in
9898
obj#meth
9999

100+
let[@inline never] lazy_ f =
101+
let x = Sys.opaque_identity (lazy (1 + f ())) in
102+
Lazy.force x
103+
100104
let () =
101105
Printexc.record_backtrace true;
102106
match
@@ -116,6 +120,7 @@ let () =
116120
42 +@+ fun _ ->
117121
(new klass)#meth @@ fun _ ->
118122
inline_object @@ fun _ ->
123+
lazy_ @@ fun _ ->
119124
bang ()
120125
with
121126
| _ -> assert false

testsuite/tests/backtrace/names.reference

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
Raised at Names.bang in file "names.ml", line 8, characters 29-39
1+
Raised at Names.bang in file "names.ml", line 9, characters 29-39
2+
Called from Names.lazy_ in file "names.ml", line 101, characters 41-45
3+
Called from CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 37, characters 17-27
4+
Re-raised at CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 42, characters 4-11
25
Called from Names.inline_object.object#othermeth in file "names.ml", line 96, characters 6-10
36
Called from Names.inline_object.object#meth in file "names.ml", line 94, characters 6-26
47
Called from Names.klass2#othermeth.(fun) in file "names.ml", line 88, characters 18-22
@@ -23,4 +26,4 @@ Called from Names.Mod1.Nested.apply in file "names.ml", line 21, characters 33-3
2326
Called from Names.fn_poly in file "names.ml", line 17, characters 2-5
2427
Called from Names.fn_function in file "names.ml", line 14, characters 9-13
2528
Called from Names.fn_multi in file "names.ml", line 11, characters 36-40
26-
Called from Names in file "names.ml", line 103, characters 4-445
29+
Called from Names in file "names.ml", line 107, characters 4-467
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Raised at Names_partial_application.bang in file "names_partial_application.ml", line 9, characters 29-39
2+
Called from Names_partial_application.labelled_arguments_partial.f in file "names_partial_application.ml", line 12, characters 38-42
3+
Called from Names_partial_application.labelled_arguments_partial in file "names_partial_application.ml", line 14, characters 2-15
4+
Called from Names_partial_application in file "names_partial_application.ml", line 20, characters 4-54
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
(* TEST
2+
flags = "-g"
3+
* bytecode
4+
reference = "${test_source_directory}/names_partial_application.byte.reference"
5+
* native
6+
reference = "${test_source_directory}/names_partial_application.opt.reference"
7+
*)
8+
9+
let[@inline never] bang () = raise Exit
10+
11+
let[@inline never] labelled_arguments_partial k =
12+
let[@inline never] f ~a = ignore a; k (); fun ~b -> ignore b; () in
13+
let partial = Sys.opaque_identity (f ~b:1) in
14+
partial ~a:();
15+
42
16+
17+
let () =
18+
Printexc.record_backtrace true;
19+
match
20+
labelled_arguments_partial @@ fun _ ->
21+
bang ()
22+
with
23+
| _ -> assert false
24+
| exception Exit ->
25+
Printexc.print_backtrace stdout
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Raised at Names_partial_application.bang in file "names_partial_application.ml", line 9, characters 29-39
2+
Called from Names_partial_application.labelled_arguments_partial.f in file "names_partial_application.ml", line 12, characters 38-42
3+
Called from Names_partial_application.labelled_arguments_partial.(partial) in file "names_partial_application.ml", line 13, characters 37-45
4+
Called from Names_partial_application.labelled_arguments_partial in file "names_partial_application.ml", line 14, characters 2-15
5+
Called from Names_partial_application in file "names_partial_application.ml", line 20, characters 4-54

testsuite/tests/translprim/locs.reference

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,34 @@ an expression
99
another expression
1010
locs.ml, 40, 14, 49
1111
yet another expression
12-
Locs.local_no_arg
13-
Locs.fn_multi
14-
Locs.fn_function
15-
Locs.fn_poly
16-
Locs.Mod1.Nested.apply
17-
Locs.anon
18-
Locs.anon
19-
Locs.anon.(fun)
20-
Locs.double_anon
21-
Locs.double_anon.(fun)
22-
Locs.double_anon.(fun)
23-
Locs.local
24-
Locs.local.inner
25-
Locs.double_local
26-
Locs.double_local.inner1
27-
Locs.double_local.inner1.inner2
28-
Locs.local_no_arg.(fun)
29-
Locs.local_no_arg.inner
30-
Locs.curried
31-
Locs.curried.inner
32-
Locs.local_module
33-
Locs.local_module.N.r
34-
Locs.local_module.N.foo
35-
Locs.Functor.fn
36-
Locs.Rec1.fn
37-
Locs.Rec2.fn
38-
Locs.(+@+)
39-
Locs.klass#meth
40-
Locs.inline_object.object#meth
41-
Locs.inline_object.object#othermeth
42-
Locs.bang
12+
Locs.local_no_arg.(partial)
13+
Locs.fn_multi.(partial)
14+
Locs.fn_function.(partial)
15+
Locs.fn_poly.(partial)
16+
Locs.Mod1.Nested.apply.(partial)
17+
Locs.anon.(partial)
18+
Locs.anon.(partial)
19+
Locs.anon.(fun).(partial)
20+
Locs.double_anon.(partial)
21+
Locs.double_anon.(fun).(partial)
22+
Locs.double_anon.(fun).(partial)
23+
Locs.local.(partial)
24+
Locs.local.inner.(partial)
25+
Locs.double_local.(partial)
26+
Locs.double_local.inner1.(partial)
27+
Locs.double_local.inner1.inner2.(partial)
28+
Locs.local_no_arg.(fun).(partial)
29+
Locs.local_no_arg.inner.(partial)
30+
Locs.curried.(partial)
31+
Locs.curried.inner.(partial)
32+
Locs.local_module.(partial)
33+
Locs.local_module.N.r.(partial)
34+
Locs.local_module.N.foo.(partial)
35+
Locs.Functor.fn.(partial)
36+
Locs.Rec1.fn.(partial)
37+
Locs.Rec2.fn.(partial)
38+
Locs.(+@+).(partial)
39+
Locs.klass#meth.(partial)
40+
Locs.inline_object.object#meth.(partial)
41+
Locs.inline_object.object#othermeth.(partial)
42+
Locs.bang.(partial)

0 commit comments

Comments
 (0)