Skip to content

Commit 79fdc00

Browse files
authored
flambda-backend: Mixed constructor args (#2508)
* tmp * Update comment and factor out element_repr * Implement core of variant code * Some progress * Get more things working * Fix some bugs * Remove lies about tags being 0 * Improve and fix bugs in error messages * Update existing tests * Add constructor args to generated tests * make fmt * Restore bytecode test to same size * Fix extensible variant bug * Add extensible variant typing tests * Commit half-failing test * chamelon * Fix layout bug and add more tests * Move a giant chunk of code closer to where it was at the base of this diff * Fix test generation to do all-float constructors * Fix whitespace in tests + build * Fix upstream build, I hope * Get rid of layout_field * [make fmt] and remove some straggling layout_fields * Remove debug code * improve garbled comment * Add some more tests * Refactor inlined record error message to fix infelicity * Fix rec check * rename 'mixed record' to 'mixed product' and fix toplevel printing * Add test for recursive mixed blocks * comment misleading support * Review: update comment to note dummy value * minor cleanups from review * note infelicity in comment * Update tests due to shelving of #2504
1 parent 54788fa commit 79fdc00

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+19735
-1634
lines changed

boot/ocamlc

7.12 KB
Binary file not shown.

bytecomp/bytegen.ml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ let rec size_of_lambda env = function
239239
| Lprim (Pmakearray (Pfloatarray, _, _), args, _)
240240
| Lprim (Pmakefloatblock _, args, _) ->
241241
RHS_floatblock (List.length args)
242-
| Lprim (Pmakemixedblock (_, _, _), args, _) ->
242+
| Lprim (Pmakemixedblock (_, _, _, _), args, _) ->
243243
RHS_faux_mixedblock (List.length args)
244244
| Lprim (Pmakearray (Pgenarray, _, _), _, _) ->
245245
(* Pgenarray is excluded from recursive bindings by the
@@ -929,7 +929,7 @@ let rec comp_expr stack_info env exp sz cont =
929929
let cont = add_pseudo_event loc !compunit_name cont in
930930
comp_args stack_info env args sz
931931
(Kmakefloatblock (List.length args) :: cont)
932-
| Lprim(Pmakemixedblock (_, shape, _), args, loc) ->
932+
| Lprim(Pmakemixedblock (tag, _, shape, _), args, loc) ->
933933
(* There is no notion of a mixed block at runtime in bytecode. Further,
934934
source-level unboxed types are represented as boxed in bytecode, so
935935
no ceremony is needed to box values before inserting them into
@@ -938,10 +938,7 @@ let rec comp_expr stack_info env exp sz cont =
938938
let total_len = shape.value_prefix_len + Array.length shape.flat_suffix in
939939
let cont = add_pseudo_event loc !compunit_name cont in
940940
comp_args stack_info env args sz
941-
(* CR mixed blocks v1: We will need to use the actual tag instead of [0]
942-
once mixed blocks can have non-zero tags.
943-
*)
944-
(Kmake_faux_mixedblock (total_len, 0) :: cont)
941+
(Kmake_faux_mixedblock (total_len, tag) :: cont)
945942
| Lprim((Pmakearray (kind, _, _)) as p, args, loc) ->
946943
let cont = add_pseudo_event loc !compunit_name cont in
947944
begin match kind with

lambda/lambda.ml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ type primitive =
145145
| Pmakeblock of int * mutable_flag * block_shape * alloc_mode
146146
| Pmakefloatblock of mutable_flag * alloc_mode
147147
| Pmakeufloatblock of mutable_flag * alloc_mode
148-
| Pmakemixedblock of mutable_flag * mixed_block_shape * alloc_mode
148+
| Pmakemixedblock of int * mutable_flag * mixed_block_shape * alloc_mode
149149
| Pfield of int * immediate_or_pointer * field_read_semantics
150150
| Pfield_computed of field_read_semantics
151151
| Psetfield of int * immediate_or_pointer * initialization_or_assignment
@@ -354,7 +354,7 @@ and mixed_block_write =
354354
| Mwrite_value_prefix of immediate_or_pointer
355355
| Mwrite_flat_suffix of flat_element
356356

357-
and mixed_block_shape = Types.mixed_record_shape =
357+
and mixed_block_shape = Types.mixed_product_shape =
358358
{ value_prefix_len : int;
359359
flat_suffix : flat_element array;
360360
}
@@ -838,7 +838,11 @@ let layout_block = Pvalue Pgenval
838838
let layout_list =
839839
Pvalue (Pvariant { consts = [0] ;
840840
non_consts = [0, Constructor_uniform [Pgenval; Pgenval]] })
841-
let layout_field = Pvalue Pgenval
841+
let layout_tuple_element = Pvalue Pgenval
842+
let layout_value_field = Pvalue Pgenval
843+
let layout_tmc_field = Pvalue Pgenval
844+
let layout_optional_arg = Pvalue Pgenval
845+
let layout_variant_arg = Pvalue Pgenval
842846
let layout_exception = Pvalue Pgenval
843847
let layout_function = Pvalue Pgenval
844848
let layout_object = Pvalue Pgenval
@@ -1239,17 +1243,17 @@ let transl_prim mod_name name =
12391243
| exception Not_found ->
12401244
fatal_error ("Primitive " ^ name ^ " not found.")
12411245

1242-
let transl_mixed_record_shape : Types.mixed_record_shape -> mixed_block_shape =
1246+
let transl_mixed_product_shape : Types.mixed_product_shape -> mixed_block_shape =
12431247
fun x -> x
12441248

12451249
let count_mixed_block_values_and_floats =
12461250
Types.count_mixed_record_values_and_floats
12471251

1248-
type mixed_block_element = Types.mixed_record_element =
1252+
type mixed_block_element = Types.mixed_product_element =
12491253
| Value_prefix
12501254
| Flat_suffix of flat_element
12511255

1252-
let get_mixed_block_element = Types.get_mixed_record_element
1256+
let get_mixed_block_element = Types.get_mixed_product_element
12531257

12541258
(* Compile a sequence of expressions *)
12551259

@@ -1623,7 +1627,7 @@ let primitive_may_allocate : primitive -> alloc_mode option = function
16231627
| Pmakeblock (_, _, _, m) -> Some m
16241628
| Pmakefloatblock (_, m) -> Some m
16251629
| Pmakeufloatblock (_, m) -> Some m
1626-
| Pmakemixedblock (_, _, m) -> Some m
1630+
| Pmakemixedblock (_, _, _, m) -> Some m
16271631
| Pfield _ | Pfield_computed _ | Psetfield _ | Psetfield_computed _ -> None
16281632
| Pfloatfield (_, _, m) -> Some m
16291633
| Pufloatfield _ -> None
@@ -1770,7 +1774,7 @@ let array_ref_kind_result_layout = function
17701774
| Pintarray_ref -> layout_int
17711775
| Pfloatarray_ref _ -> layout_boxed_float Pfloat64
17721776
| Punboxedfloatarray_ref bf -> layout_unboxed_float bf
1773-
| Pgenarray_ref _ | Paddrarray_ref -> layout_field
1777+
| Pgenarray_ref _ | Paddrarray_ref -> layout_value_field
17741778
| Punboxedintarray_ref Pint32 -> layout_unboxed_int32
17751779
| Punboxedintarray_ref Pint64 -> layout_unboxed_int64
17761780
| Punboxedintarray_ref Pnativeint -> layout_unboxed_nativeint
@@ -1793,7 +1797,7 @@ let primitive_result_layout (p : primitive) =
17931797
| Pmakeblock _ | Pmakefloatblock _ | Pmakearray _ | Pduprecord _
17941798
| Pmakeufloatblock _ | Pmakemixedblock _
17951799
| Pduparray _ | Pbigarraydim _ | Pobj_dup -> layout_block
1796-
| Pfield _ | Pfield_computed _ -> layout_field
1800+
| Pfield _ | Pfield_computed _ -> layout_value_field
17971801
| Punboxed_product_field (field, layouts) -> (Array.of_list layouts).(field)
17981802
| Pmake_unboxed_product layouts -> layout_unboxed_product layouts
17991803
| Pfloatfield _ -> layout_boxed_float Pfloat64
@@ -1806,7 +1810,7 @@ let primitive_result_layout (p : primitive) =
18061810
| Punbox_float float_kind -> Punboxed_float float_kind
18071811
| Pmixedfield (_, kind, _) -> begin
18081812
match kind with
1809-
| Mread_value_prefix _ -> layout_field
1813+
| Mread_value_prefix _ -> layout_value_field
18101814
| Mread_flat_suffix proj -> begin
18111815
match proj with
18121816
| Flat_read_imm -> layout_int

lambda/lambda.mli

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ type primitive =
102102
| Pmakeblock of int * mutable_flag * block_shape * alloc_mode
103103
| Pmakefloatblock of mutable_flag * alloc_mode
104104
| Pmakeufloatblock of mutable_flag * alloc_mode
105-
| Pmakemixedblock of mutable_flag * mixed_block_shape * alloc_mode
105+
| Pmakemixedblock of int * mutable_flag * mixed_block_shape * alloc_mode
106106
| Pfield of int * immediate_or_pointer * field_read_semantics
107107
| Pfield_computed of field_read_semantics
108108
| Psetfield of int * immediate_or_pointer * initialization_or_assignment
@@ -720,8 +720,17 @@ val layout_boxed_float : boxed_float -> layout
720720
val layout_unboxed_float : boxed_float -> layout
721721
val layout_boxedint : boxed_integer -> layout
722722
val layout_boxed_vector : Primitive.boxed_vector -> layout
723-
(* A layout that is Pgenval because it is the field of a block *)
724-
val layout_field : layout
723+
(* A layout that is Pgenval because it is the field of a tuple *)
724+
val layout_tuple_element : layout
725+
(* A layout that is Pgenval because it is the arg of a polymorphic variant *)
726+
val layout_variant_arg : layout
727+
(* A layout that is Pgenval because it is the field of a block being considered
728+
for the tmc transformation
729+
*)
730+
val layout_tmc_field : layout
731+
(* A layout that is Pgenval because it is an optional argument *)
732+
val layout_optional_arg : layout
733+
val layout_value_field : layout
725734
val layout_lazy : layout
726735
val layout_lazy_contents : layout
727736
(* A layout that is Pgenval because we are missing layout polymorphism *)
@@ -780,7 +789,7 @@ val transl_value_path: scoped_location -> Env.t -> Path.t -> lambda
780789
val transl_extension_path: scoped_location -> Env.t -> Path.t -> lambda
781790
val transl_class_path: scoped_location -> Env.t -> Path.t -> lambda
782791

783-
val transl_mixed_record_shape: Types.mixed_record_shape -> mixed_block_shape
792+
val transl_mixed_product_shape: Types.mixed_product_shape -> mixed_block_shape
784793
val count_mixed_block_values_and_floats : mixed_block_shape -> int * int
785794

786795
type mixed_block_element =

lambda/matching.ml

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,18 @@ open Printpat
9999
module Scoped_location = Debuginfo.Scoped_location
100100

101101
type error =
102-
Non_value_layout of Jkind.Violation.t
102+
| Void_layout
103103
| Illegal_record_field of Jkind.const
104104

105105
exception Error of Location.t * error
106106

107107
let dbg = false
108108

109-
(* CR layouts v5: When we're ready to allow non-values, these can be deleted or
110-
changed to check for void. *)
111-
let jkind_layout_must_be_value loc jkind =
112-
match Jkind.(sub_or_error jkind (value ~why:V1_safety_check)) with
113-
| Ok _ -> ()
114-
| Error e -> raise (Error (loc, Non_value_layout e))
109+
let jkind_layout_default_to_value_and_check_not_void loc jkind =
110+
match Jkind.get_default_value jkind with
111+
| Void -> raise (Error (loc, Void_layout))
112+
| _ -> ()
113+
;;
115114

116115
(* CR layouts v5: This function is only used for sanity checking the
117116
typechecker. When we allow arbitrary layouts in structures, it will have
@@ -1793,7 +1792,9 @@ let get_pat_args_constr p rem =
17931792
match p with
17941793
| { pat_desc = Tpat_construct (_, {cstr_arg_jkinds}, args, _) } ->
17951794
List.iteri
1796-
(fun i arg -> jkind_layout_must_be_value arg.pat_loc cstr_arg_jkinds.(i))
1795+
(fun i arg ->
1796+
jkind_layout_default_to_value_and_check_not_void
1797+
arg.pat_loc cstr_arg_jkinds.(i))
17971798
args;
17981799
(* CR layouts v5: This sanity check will have to go (or be replaced with a
17991800
void-specific check) when we have other non-value sorts *)
@@ -1809,27 +1810,49 @@ let get_expr_args_constr ~scopes head (arg, _mut, sort, layout) rem =
18091810
let loc = head_loc ~scopes head in
18101811
(* CR layouts v5: This sanity check should be removed or changed to
18111812
specifically check for void when we add other non-value sorts. *)
1812-
Array.iter (fun jkind -> jkind_layout_must_be_value head.pat_loc jkind)
1813+
Array.iter (fun jkind ->
1814+
jkind_layout_default_to_value_and_check_not_void head.pat_loc jkind)
18131815
cstr.cstr_arg_jkinds;
1814-
let make_field_accesses binding_kind first_pos last_pos argl =
1815-
let rec make_args pos =
1816-
if pos > last_pos then
1817-
argl
1818-
else
1819-
(Lprim (Pfield (pos, Pointer, Reads_agree), [ arg ], loc), binding_kind,
1820-
Jkind.Sort.for_constructor_arg, layout_field)
1821-
:: make_args (pos + 1)
1816+
let make_field_access binding_kind ~field ~pos =
1817+
let prim =
1818+
match cstr.cstr_shape with
1819+
| Constructor_uniform_value -> Pfield (pos, Pointer, Reads_agree)
1820+
| Constructor_mixed shape ->
1821+
let read =
1822+
match Types.get_mixed_product_element shape field with
1823+
| Value_prefix -> Mread_value_prefix Pointer
1824+
| Flat_suffix flat ->
1825+
let flat_read =
1826+
match flat with
1827+
| Imm -> Flat_read_imm
1828+
| Float64 -> Flat_read_float64
1829+
| Float ->
1830+
Misc.fatal_error
1831+
"unexpected flat float of layout value in \
1832+
constructor field"
1833+
in
1834+
Mread_flat_suffix flat_read
1835+
in
1836+
Pmixedfield (pos, read, Reads_agree)
18221837
in
1823-
make_args first_pos
1838+
let jkind = cstr.cstr_arg_jkinds.(field) in
1839+
let sort = Jkind.sort_of_jkind jkind in
1840+
let layout = Typeopt.layout_of_sort head.pat_loc sort in
1841+
(Lprim (prim, [ arg ], loc), binding_kind, sort, layout)
18241842
in
18251843
if cstr.cstr_inlined <> None then
18261844
(arg, Alias, sort, layout) :: rem
18271845
else
18281846
match cstr.cstr_repr with
18291847
| Variant_boxed _ ->
1830-
make_field_accesses Alias 0 (cstr.cstr_arity - 1) rem
1848+
List.init cstr.cstr_arity
1849+
(fun i -> make_field_access Alias ~field:i ~pos:i)
1850+
@ rem
18311851
| Variant_unboxed -> (arg, Alias, sort, layout) :: rem
1832-
| Variant_extensible -> make_field_accesses Alias 1 cstr.cstr_arity rem
1852+
| Variant_extensible ->
1853+
List.init cstr.cstr_arity
1854+
(fun i -> make_field_access Alias ~field:i ~pos:(i+1))
1855+
@ rem
18331856

18341857
let divide_constructor ~scopes ctx pm =
18351858
divide
@@ -1850,8 +1873,8 @@ let get_expr_args_variant_nonconst ~scopes head (arg, _mut, _sort, _layout)
18501873
rem =
18511874
let loc = head_loc ~scopes head in
18521875
let field_prim = nonconstant_variant_field 1 in
1853-
(Lprim (field_prim, [ arg ], loc), Alias, Jkind.Sort.for_constructor_arg,
1854-
layout_field)
1876+
(Lprim (field_prim, [ arg ], loc), Alias, Jkind.Sort.for_variant_arg,
1877+
layout_variant_arg)
18551878
:: rem
18561879

18571880
let divide_variant ~scopes row ctx { cases = cl; args; default = def } =
@@ -2094,7 +2117,7 @@ let get_expr_args_tuple ~scopes head (arg, _mut, _sort, _layout) rem =
20942117
rem
20952118
else
20962119
(Lprim (Pfield (pos, Pointer, Reads_agree), [ arg ], loc), Alias,
2097-
Jkind.Sort.for_tuple_element, layout_field)
2120+
Jkind.Sort.for_tuple_element, layout_tuple_element)
20982121
:: make_args (pos + 1)
20992122
in
21002123
make_args 0
@@ -3963,9 +3986,11 @@ let for_let ~scopes ~arg_sort ~return_layout loc param pat body =
39633986
(* Easy case since variables are available *)
39643987
let for_tupled_function ~scopes ~return_layout loc paraml pats_act_list partial =
39653988
let partial = check_partial_list pats_act_list partial in
3966-
(* The arguments of a tupled function are always values since they must be fields *)
3989+
(* The arguments of a tupled function are always values since they must be
3990+
tuple elements *)
39673991
let args =
3968-
List.map (fun id -> (Lvar id, Strict, Jkind.Sort.for_tuple_element, layout_field))
3992+
List.map (fun id -> (Lvar id, Strict, Jkind.Sort.for_tuple_element,
3993+
layout_tuple_element))
39693994
paraml
39703995
in
39713996
let handler =
@@ -4158,11 +4183,10 @@ let for_optional_arg_default
41584183
open Format
41594184

41604185
let report_error ppf = function
4161-
| Non_value_layout err ->
4186+
| Void_layout ->
41624187
fprintf ppf
4163-
"Non-value detected in translation:@ Please report this error to \
4164-
the Jane Street compilers team.@ %a"
4165-
(Jkind.Violation.report_with_name ~name:"this expression") err
4188+
"Void layout detected in translation:@ Please report this error to \
4189+
the Jane Street compilers team."
41664190
| Illegal_record_field c ->
41674191
fprintf ppf
41684192
"Sort %s detected where value was expected in a record field:@ Please \

lambda/printlambda.ml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,15 @@ let primitive ppf = function
415415
| Pmakeufloatblock (Mutable, mode) ->
416416
fprintf ppf "make%sufloatblock Mutable"
417417
(alloc_mode_if_local mode)
418-
| Pmakemixedblock (Immutable, abs, mode) ->
419-
fprintf ppf "make%amixedblock Immutable%a"
420-
alloc_mode mode mixed_block_shape abs
421-
| Pmakemixedblock (Immutable_unique, abs, mode) ->
422-
fprintf ppf "make%amixedblock Immutable_unique%a"
423-
alloc_mode mode mixed_block_shape abs
424-
| Pmakemixedblock (Mutable, abs, mode) ->
425-
fprintf ppf "make%amixedblock Mutable%a"
426-
alloc_mode mode mixed_block_shape abs
418+
| Pmakemixedblock (tag, Immutable, abs, mode) ->
419+
fprintf ppf "make%amixedblock %i Immutable%a"
420+
alloc_mode mode tag mixed_block_shape abs
421+
| Pmakemixedblock (tag, Immutable_unique, abs, mode) ->
422+
fprintf ppf "make%amixedblock %i Immutable_unique%a"
423+
alloc_mode mode tag mixed_block_shape abs
424+
| Pmakemixedblock (tag, Mutable, abs, mode) ->
425+
fprintf ppf "make%amixedblock %i Mutable%a"
426+
alloc_mode mode tag mixed_block_shape abs
427427
| Pfield (n, ptr, sem) ->
428428
let instr =
429429
match ptr, sem with

lambda/simplif.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,9 @@ let simplify_lets lam =
586586
let slbody = simplif lbody in
587587
begin try
588588
let kind = match kind_ref with
589-
| None -> Lambda.layout_field
589+
| None ->
590+
(* This is a [Pmakeblock] so the fields are all values *)
591+
Lambda.layout_value_field
590592
| Some [field_kind] -> Pvalue field_kind
591593
| Some _ -> assert false
592594
in
@@ -801,10 +803,9 @@ let split_default_wrapper ~id:fun_id ~kind ~params ~return ~body
801803
let inner_id = Ident.create_local (Ident.name fun_id ^ "_inner") in
802804
let map_param (p : Lambda.lparam) =
803805
try
804-
(* If the param is optional, then it must be a value *)
805806
{
806807
name = List.assoc p.name map;
807-
layout = Lambda.layout_field;
808+
layout = Lambda.layout_optional_arg;
808809
attributes = Lambda.default_param_attribute;
809810
mode = p.mode
810811
}

lambda/tmc.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ end = struct
169169
List.fold_right (fun binding body ->
170170
match binding with
171171
| None -> body
172-
| Some (v, lam) -> Llet(Strict, Lambda.layout_field, v, lam, body)
172+
| Some (v, lam) -> Llet(Strict, Lambda.layout_tmc_field, v, lam, body)
173173
) bindings body in
174174
fun ~block_id constr body ->
175175
bind_list ~block_id ~arg_offset:0 constr.before @@ fun vbefore ->
@@ -915,7 +915,9 @@ let rec choice ctx t =
915915
(* we don't handle { foo with x = ...; y = recursive-call } *)
916916
| Pduprecord _
917917

918-
(* we don't handle all-float records or mixed blocks *)
918+
(* we don't handle all-float records or mixed blocks. If we
919+
did, we'd need to remove references to Lambda.layout_tmc_field
920+
*)
919921
| Pmakefloatblock _
920922
| Pmakeufloatblock _
921923
| Pmakemixedblock _

0 commit comments

Comments
 (0)