From 322c18869e6a707b33e2ab977e9ab59a2bc386f0 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Tue, 30 May 2023 10:25:39 +0100 Subject: [PATCH 01/30] Bugfix for GC backlog tracking (#1387) * Reset GC backlog at each cycle unconditionally * Change GC backlog units to be words rather than heap fractions --- ocaml/runtime/major_gc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ocaml/runtime/major_gc.c b/ocaml/runtime/major_gc.c index 5469d0325b7..e9cd9fcdec0 100644 --- a/ocaml/runtime/major_gc.c +++ b/ocaml/runtime/major_gc.c @@ -69,7 +69,12 @@ extern value caml_fl_merge; /* Defined in freelist.c. */ static char *redarken_first_chunk = NULL; static char *sweep_chunk; -static double p_backlog = 0.0; /* backlog for the gc speedup parameter */ + +/* Part of the major slice left for future slices since otherwise a + single slice would be too big. + + In units of words so that it remains consistent across heap size growth */ +static uintnat backlog_words = 0; int caml_gc_subphase; /* Subphase_{mark_roots,mark_main,mark_final} */ @@ -398,6 +403,7 @@ static void start_cycle (void) CAMLassert (redarken_first_chunk == NULL); caml_gc_message (0x01, "Starting new major GC cycle\n"); marked_words = 0; + backlog_words = 0; caml_darken_all_roots_start (); caml_gc_phase = Phase_mark; heap_wsz_at_cycle_start = Caml_state->stat_heap_wsz; @@ -996,10 +1002,10 @@ void caml_major_collection_slice (intnat howmuch) } if (p < dp) p = dp; if (p < caml_extra_heap_resources) p = caml_extra_heap_resources; - p += p_backlog; - p_backlog = 0.0; + p += (double)backlog_words / (double)Caml_state->stat_heap_wsz; + backlog_words = 0; if (p > 0.3){ - p_backlog = p - 0.3; + backlog_words = (uintnat)((p - 0.3) * (double)Caml_state->stat_heap_wsz); p = 0.3; } @@ -1018,8 +1024,8 @@ void caml_major_collection_slice (intnat howmuch) ARCH_INTNAT_PRINTF_FORMAT "du\n", (intnat) (p * 1000000)); caml_gc_message (0x40, "work backlog = %" - ARCH_INTNAT_PRINTF_FORMAT "du\n", - (intnat) (p_backlog * 1000000)); + ARCH_INTNAT_PRINTF_FORMAT "d\n", + backlog_words); for (i = 0; i < caml_major_window; i++){ caml_major_ring[i] += p / caml_major_window; @@ -1164,7 +1170,6 @@ void caml_major_collection_slice (intnat howmuch) void caml_finish_major_cycle (void) { if (caml_gc_phase == Phase_idle){ - p_backlog = 0.0; /* full major GC cycle, the backlog becomes irrelevant */ start_cycle (); } while (caml_gc_phase == Phase_mark) mark_slice (LONG_MAX); From f78e39a28af40aeb21871581d37bbb7ee960f740 Mon Sep 17 00:00:00 2001 From: Richard Eisenberg Date: Tue, 30 May 2023 07:37:10 -0400 Subject: [PATCH 02/30] Remove layout variables from [val]s (#1423) * Remove layout variables from [val]s * Actually update tests * bootstrap --- ocaml/boot/ocamlc | Bin 3437868 -> 3441127 bytes ocaml/boot/ocamllex | Bin 372168 -> 372168 bytes .../testsuite/tests/typing-layouts/basics.ml | 12 +++++ .../tests/typing-layouts/basics_alpha.ml | 48 ++++++++++++++++++ .../tests/typing-layouts/basics_beta.ml | 12 +++++ .../test.compilers.reference | 4 +- ocaml/typing/typetexp.ml | 5 ++ 7 files changed, 79 insertions(+), 2 deletions(-) diff --git a/ocaml/boot/ocamlc b/ocaml/boot/ocamlc index 6e3cbcd17982656027df01f35e2a244d97f8cd5d..8635bc10ac1942b680c57e023bcc8bbd3245d7a1 100755 GIT binary patch delta 244857 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

4og5)0& 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≤*ifuR8RWkz5&zNu*|< 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 delta 243617 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%0D>$Bu}*qTTA+18cT#{&|d(2)3qV4V>V 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 kR?O=r+}0UDO{Z1H~`9i9v_aD#DX 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 diff --git a/ocaml/boot/ocamllex b/ocaml/boot/ocamllex index 1c22ad1473c6f10d2661950f330c9c7a950a76d4..dd4ef8c3c13980bab829b101c8a714966c5cf015 100755 GIT binary patch delta 466 zcmV;@0WJQ>+ZM>%7J!5SgaU*Egaot&a;6ZYx#(*Aqz0+Q|7Du-dT9fff~Ey15U=*` z>pwQ*lzL9!CR#ie!i@lJb%TiEusLIJEsL>GZdco z&5-@}05UVzu-&lUETAw`bYyI4VqafSa%paKWq4ySR(ZJLu#lP2Yd?sQ(%YmHm(iyM zClGrWN_QAlUa+m+@;gIp(V>?Js0Bh0c2_QVbCa3&T;S zD$-21qy?awYKWP${O$J1mkg@~nh*mK8TgMnY;X<>0yNV?mKB$_s|6+ZM>%7J!5SgaU*Egaot&a;6Y6ssog?wFb?nxk^0G-#}fLf~Ey15NYXU zQLJ@gx;>wQCLh2Rn3uYy1vN~nxZGR&%+!`KTx_EY%WfN>D^ql2Y-wU&UsGjtFxz6EbYyI4VqafVWpOZ<;w;a1f3xiL90jiyNKG=AJEsL>Ge*h} zO9N~ORjJvmPN~XVIG`|7bYyI4VqafSa%paKWq4yS)a~j~9iDsjH7Bbi6=VeCm(iyM zClGLJMBBhGir)bwFszdwn=zLNs0Bh0=Y&lo_DbnxcPxU;ej5a@ms+R=Sr8N2s7^q5 z>y+DnhKl+#=8BiYs0AbtV##lKsLxtHgyq{@Lj-#*m-nazFc3)ovdMMhss1JBFIeol zWE+<^sRe})C?q1^xm!DBZ#BU{f>0KUm&~aJl@Q_`;I&=|8+CA%Mwe=0nthjXss)P> z|7*@i7&;P%fND{ae}PEvmkg@~nh^fHfnxn7HDlI`MgscihAWr0s|6sqDOXr^ Ims_m`ZN=Wx4FCWD diff --git a/ocaml/testsuite/tests/typing-layouts/basics.ml b/ocaml/testsuite/tests/typing-layouts/basics.ml index c0fb8840f30..5288cc23ae9 100644 --- a/ocaml/testsuite/tests/typing-layouts/basics.ml +++ b/ocaml/testsuite/tests/typing-layouts/basics.ml @@ -287,3 +287,15 @@ Error: Layout void is used here, but the appropriate layouts extension is not en (* CR layouts: This test moved to [basics_alpha.ml] as it needs a non-value sort. Bring back here when we have one enabled by default. *) + +(*******************************************) +(* Test 29: [external]s default to [value] *) + +(* CR layouts: This test moved to [basics_alpha.ml] as it needs a non-value + sort. Bring back here when we have one enabled by default. *) + +(**************************************) +(* Test 30: [val]s default to [value] *) + +(* CR layouts: This test moved to [basics_alpha.ml] as it needs a non-value + sort. Bring back here when we have one enabled by default. *) diff --git a/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml b/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml index a29befa06b4..fb03dd0616b 100644 --- a/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml +++ b/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml @@ -1395,3 +1395,51 @@ Error: This pattern matches values of type t_void but a pattern was expected which matches values of type ('a : value) t_void has layout void, which is not a sublayout of value. |}] + +(*******************************************) +(* Test 29: [external]s default to [value] *) + +(* CR layouts: this must be done in a module so that we can test the + type-checker, as opposed to the value-kind check. After we have proper + support for a non-value argument type, remove the module wrapper. +*) +module _ = struct + external eq : 'a -> 'a -> bool = "%equal" + let mk_void () : t_void = assert false + let x () = eq (mk_void ()) (mk_void ()) +end + +[%%expect{| +Line 4, characters 16-28: +4 | let x () = eq (mk_void ()) (mk_void ()) + ^^^^^^^^^^^^ +Error: This expression has type t_void but an expression was expected of type + ('a : value) + t_void has layout void, which is not a sublayout of value. +|}] + +(**************************************) +(* Test 30: [val]s default to [value] *) + +(* CR layouts: this must be done in a module so that we can test the + type-checker, as opposed to the value-kind check. After we have proper + support for a non-value argument type, remove the module wrapper. +*) +module _ = struct + module M : sig + val f : 'a -> 'a + end = struct + let f x = x + end + + let g (x : t_void) = M.f x +end + +[%%expect{| +Line 8, characters 27-28: +8 | let g (x : t_void) = M.f x + ^ +Error: This expression has type t_void but an expression was expected of type + ('a : value) + t_void has layout void, which is not a sublayout of value. +|}] diff --git a/ocaml/testsuite/tests/typing-layouts/basics_beta.ml b/ocaml/testsuite/tests/typing-layouts/basics_beta.ml index db78b4a5795..5d594a189f3 100644 --- a/ocaml/testsuite/tests/typing-layouts/basics_beta.ml +++ b/ocaml/testsuite/tests/typing-layouts/basics_beta.ml @@ -493,3 +493,15 @@ Error: Layout void is used here, but the appropriate layouts extension is not en (* CR layouts v2: This test moved to [basics_alpha.ml] as it needs a non-value sort. Bring back here when we have one. *) + +(*******************************************) +(* Test 29: [external]s default to [value] *) + +(* CR layouts v2: This test moved to [basics_alpha.ml] as it needs a non-value + sort. Bring back here when we have one. *) + +(**************************************) +(* Test 30: [val]s default to [value] *) + +(* CR layouts v2: This test moved to [basics_alpha.ml] as it needs a non-value + sort. Bring back here when we have one. *) diff --git a/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference b/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference index 493ac921989..642d7fd8c8a 100644 --- a/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference +++ b/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference @@ -2,7 +2,7 @@ File "main.ml", line 1, characters 8-11: 1 | let _ = A.a = B.b ^^^ Error: This expression has type M.a but an expression was expected of type - ('a : '_representable_layout_1) - M.a has layout any, which is not representable. + ('a : value) + M.a has layout any, which is not a sublayout of value. No .cmi file found containing M.a. Hint: Adding "m" to your dependencies might help. diff --git a/ocaml/typing/typetexp.ml b/ocaml/typing/typetexp.ml index ae0ebcd2ae3..1fa4c6fefdf 100644 --- a/ocaml/typing/typetexp.ml +++ b/ocaml/typing/typetexp.ml @@ -997,6 +997,11 @@ let transl_type_scheme env styp = begin_def(); let typ = transl_simple_type env ~closed:false Alloc_mode.Global styp in end_def(); + (* This next line is very important: it stops [val] and [external] + declarations from having undefaulted layout variables. Without + this line, we might accidentally export a layout-flexible definition + from a compilation unit, which would lead to miscompilation. *) + remove_mode_and_layout_variables typ.ctyp_type; generalize typ.ctyp_type; typ From 8383a85efcf2461db7944b5ac762188d4bdb8af4 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Tue, 30 May 2023 16:50:15 +0100 Subject: [PATCH 03/30] Bugfix for caml_switch_runtime_locking_scheme (#1429) --- ocaml/otherlibs/systhreads/st_stubs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ocaml/otherlibs/systhreads/st_stubs.c b/ocaml/otherlibs/systhreads/st_stubs.c index 4003ab62073..3a46363332d 100644 --- a/ocaml/otherlibs/systhreads/st_stubs.c +++ b/ocaml/otherlibs/systhreads/st_stubs.c @@ -880,6 +880,8 @@ CAMLprim value caml_thread_yield(value unit) /* ML */ caml_raise_async_if_exception(caml_process_pending_signals_exn(), "signal handler"); caml_thread_save_runtime_state(); + /* caml_locking_scheme may have changed in caml_process_pending_signals_exn */ + s = atomic_load(&caml_locking_scheme); s->yield(s->context); if (atomic_load(&caml_locking_scheme) != s) { /* The lock we have is no longer the runtime lock */ From 3485ccf7aaf7348f6393b2711700abacb5963475 Mon Sep 17 00:00:00 2001 From: Xavier Clerc Date: Tue, 30 May 2023 19:43:43 +0100 Subject: [PATCH 04/30] Fix swapgil test C warnings (#1430) Fix swapgil test C warnings. --- ocaml/testsuite/tests/lib-systhreads/swapgil_stubs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ocaml/testsuite/tests/lib-systhreads/swapgil_stubs.c b/ocaml/testsuite/tests/lib-systhreads/swapgil_stubs.c index 44caae53b39..558a8472155 100644 --- a/ocaml/testsuite/tests/lib-systhreads/swapgil_stubs.c +++ b/ocaml/testsuite/tests/lib-systhreads/swapgil_stubs.c @@ -16,6 +16,7 @@ value blocking_section(value unused) { caml_enter_blocking_section(); caml_leave_blocking_section(); + return Val_unit; } @@ -115,6 +116,7 @@ value swap_gil_setup(value unused) caml_default_locking_scheme.thread_start = runtime_thread_start; caml_default_locking_scheme.thread_stop = runtime_thread_stop; started = 1; + return Val_unit; } value swap_gil(value unused) From e2ba30a653d5e0912d32cc59fac20e45545831c7 Mon Sep 17 00:00:00 2001 From: Richard Eisenberg Date: Wed, 31 May 2023 12:10:38 -0400 Subject: [PATCH 05/30] Use layout histories to produce better errors (#1340) * Add layout histories While disabled for now, these histories will allow for us to include nice information in error messages. This commit also includes code to common up layouts when saving a cmi. * bootstrap; fix errors --- native_toplevel/opttopdirs.ml | 2 +- ocaml/boot/ocamlc | Bin 3441127 -> 3456781 bytes ocaml/boot/ocamllex | Bin 372168 -> 372168 bytes ocaml/debugger/loadprinter.ml | 2 +- ocaml/lambda/matching.ml | 6 +- ocaml/lambda/translcore.ml | 28 +- ocaml/lambda/translcore.mli | 2 +- ocaml/lambda/translmod.ml | 12 +- ocaml/lambda/translmod.mli | 2 +- ocaml/ocamldoc/odoc_sig.ml | 2 +- ocaml/parsing/builtin_attributes.ml | 34 +- ocaml/parsing/builtin_attributes.mli | 3 +- ocaml/parsing/location.ml | 1 + ocaml/parsing/location.mli | 2 +- .../tests/typing-layouts-missing-cmi/c.ml | 5 +- .../testsuite/tests/typing-layouts/basics.ml | 6 + .../tests/typing-layouts/basics_alpha.ml | 19 + .../tests/typing-layouts/basics_beta.ml | 8 +- .../test.compilers.reference | 2 +- .../test.compilers.reference | 2 +- .../test.compilers.reference | 2 +- ocaml/toplevel/genprintval.ml | 6 +- ocaml/toplevel/topdirs.ml | 7 +- ocaml/typing/ctype.ml | 188 +-- ocaml/typing/ctype.mli | 18 +- ocaml/typing/datarepr.ml | 8 +- ocaml/typing/errortrace.ml | 4 +- ocaml/typing/errortrace.mli | 4 +- ocaml/typing/includecore.ml | 7 +- ocaml/typing/includecore.mli | 2 +- ocaml/typing/layouts.ml | 1055 ++++++++++++----- ocaml/typing/layouts.mli | 289 +++-- ocaml/typing/oprint.ml | 4 +- ocaml/typing/parmatch.ml | 4 +- ocaml/typing/predef.ml | 41 +- ocaml/typing/printtyp.ml | 17 +- ocaml/typing/printtyped.ml | 4 +- ocaml/typing/subst.ml | 149 ++- ocaml/typing/typeclass.ml | 66 +- ocaml/typing/typeclass.mli | 2 +- ocaml/typing/typecore.ml | 221 ++-- ocaml/typing/typecore.mli | 3 +- ocaml/typing/typedecl.ml | 114 +- ocaml/typing/typedecl.mli | 6 +- ocaml/typing/typedecl_separability.ml | 7 +- ocaml/typing/typemod.ml | 20 +- ocaml/typing/typeopt.ml | 25 +- ocaml/typing/types.mli | 2 +- ocaml/typing/typetexp.ml | 59 +- ocaml/typing/typetexp.mli | 4 +- ocaml/utils/misc.ml | 4 + ocaml/utils/misc.mli | 3 + 52 files changed, 1576 insertions(+), 907 deletions(-) diff --git a/native_toplevel/opttopdirs.ml b/native_toplevel/opttopdirs.ml index 7d347603a91..a048a3097cb 100644 --- a/native_toplevel/opttopdirs.ml +++ b/native_toplevel/opttopdirs.ml @@ -138,7 +138,7 @@ let match_printer_type ppf desc typename = raise Exit in Ctype.begin_def(); - let ty_arg = Ctype.newvar Layouts.Layout.value in + let ty_arg = Ctype.newvar (Layouts.Layout.value ~why:Debug_printer_argument) in Ctype.unify !toplevel_env (Ctype.newconstr printer_type [ty_arg]) (Ctype.instance desc.val_type); diff --git a/ocaml/boot/ocamlc b/ocaml/boot/ocamlc index 8635bc10ac1942b680c57e023bcc8bbd3245d7a1..6620116ad3aad747d41646be69724d518e554286 100755 GIT binary patch delta 235651 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


i*Rz2e^GUWq#THV+kkPM!2riul2T33$e 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

U7=-Uj-bAjS3*+uxazYc$BWeb!52_MTbB5)%$ z-SB*1BQeM;98(mxP$4UfI!m(^MHb9OK>!ke@p`s$z$35xMIfPy9Ob{3pQ!X+oanqT z23%(4Ek!{z2zbWtyJ}a$Juetz3%T;4hM~qq0Ugjr>VnuqiLWFf@Ara7V&o zuoc6=GS;WOJdk0vw6PaCmnkt`!}0nS&=s8HNL{8x1%8M73Ak9$URAr!<{$4_AIIHq zMBChj%akQ`tbO1zbZKN$_6D?zd*r=BS<0EKRw&acb5I?dUyUy4j-NtSg6!#|x^s*z z5`GeJ46|^h(w~vzuPc?F7Ajkb1#;2`m-zjk!8U-`P@e9!t8hvv_RrAGOMwDfh;!*_ zTllc>OHkG3Mj*_DBUhQpNH6OI7~jG?C7D}v`g}-G{)H*nW1hya_&%##_glhm<8LS~ zY(FLdrLCTgro<0~5G*<0K>PVhSaaTr-;Gj?78wVaf+KF1gg7IgM++-1UuXD^;?*j# zM=vUx56YGONT4ruItR!*e1lCvmMQZKiWPf)@=-{={}Y8H#*@OLD8d`0t*j+(6Rxst z=X1()=IVd$c_p36(O=IiePM)~QlNC@fv+{{AYvHC7Z3nddJPAOn;vX;vgc)Hp_$-t zdl4^_u-airjl}Oa14pvd)k-_lV*TC41T@bkwos*0_ELoXz1|L|4+=l8XLB!qL5Z@! z+v3h^P){9x5j(2i^>Q$b_on?XDNW&R5nBzz-nZl_?9~s?0^L{FNW=gG8$e>H-R7RM zM!96MTw?yr7pssa5Aek2M;&*43hggSM4V;?6iwS6FV@CI_a9zN~YpsTe zLSH71uR)e7{sQ)`+^oclB=EVntxCMfi=X#bf)ckVcUu(;4IC5@W_yr#*OiN*!Y|wc zC6_M_%ff!%_b}6(4Db^Nw?M^&Ft~9z@lv@(X-^eHgKa+CEXIa)=*(CwhyJfCQPxX0 zXjR>28a?+q-UuM)8vuiZp&-gL2lxe0_cx;)&IQm9GPdAXnH`@@H(pnIIWbXE+ru=C z@qizdc8r0PJw>s}v&YP7R3RArmR%t+5UzCtj>F4D7?o~So`$BSC=pthiQ9mD`!7WY zR*wUAxZaloP>;jbOl<_2P4*z1C%hEi4DKAS@Z#wh6Oqy!-{c{yfrHF?kn(cowsAW{ zaPe-EhmyO&OJpB4-VP?0DL#LqKBa9}@?j*B@_-!x-2|Q|dFRhxuu;(&oGUASB3Nfr zo}r9bn6FhHg?_euuYeFbISH!U%=_SfC=>3>lDEVm)MFhVdmvYhB`3RH7paaxN-sni zvJ$oeE8l^snA0c-r*sJ>iC1!NWp?z&4xhh_s<MPl>o>aax zur=-a152`O8OFT05J6!$WHxo$35nS8a7Y$%FX48{UI;laJWwAp&z*|R;zO1?KK_0+ zdPo`d5n(~STF+K+G7?m@FZQnKO)(<7$`uE#?q1K=hfVIg;HpnKQIHH7>}E@?M+b3f9UHsmB>(Dfowv@&suE@&3wJ39yBI=eb~JfrS#hrp!Cnat9NbDoW3HB~<7#<#Wmemd^T^VpzCSigkGPeQNuI!BikLVr)_98vA`=k) zlEuga^1bQC#uZ3#j}qx@3|523iJQz7t)!uQls7Fi+&*t3L8*85DxaghdG9D2Yr(pG z_9-#7@4RWjK4lrc(k-yA z0eB32eDPRGZ&BeiWle}(?%GV3QH-4Qv9ufj6OLufot80`G7l)R(wMFzB{oFhsZ=;9 zftif5#3JQ;EAb{zmj3mu4WYwpk=d301I=F9hxibSYZ_3ZfV^e?1jwh=kB}+B2lC4} zf5}#-;d355`Ca5(A(Vnu0?Ya%>>_;h#%1mYvF#79k(5vvY8Si`rr2Dm$2y!e?|sm)jHpX#^Q`_f{~-7T_{ln?++C0awsyrOC=b>YX~3=p*rODV zhmF|=OyiG9+^Y^_3Plm;pBZ1ULNjrj!&IA;VCtFZ^;Of1=pr=+|nm?^h4N!X486;AV7& zK`>7=?fV2egZe=TQW6*B&8W*ah>rdg8fNtaM*5gFMvnoUvwsZG!-Slmw8PlPpP)w$ zEB&kuf@tqyh^ZO|5sa~1SU=!7au)-qrjG%S8oQLG#zz!ejs1o%i6ctC{N(;%PZq<7 zJe+cNI3WCbECf{fWB;0k>+8IG#Wy(pUvWf@b@{6qf)YZ+IbYNZc54&+oD;&)T}BU zr z+DHRX%y}=)_;?n3nsPoY`WZB!P3XtZ6vbKo zb5N=-XDUVM*coj-rp)wV7Lmmx!DML;)Ky#@;hSGr0sYk%itgMP(VEk}VdVOS zk}bVpGav1VcB{51$ghu!Ic9#&1SMZb4cQ|?d>h}5Jm%MHeIL@mV1Ft2Z;2uT7h~^Q zK10hd`sgBpDumSyC41nAFvwf>RtQAYuONmrM3O7MQsx_0=&~2;acHs=DeE|Nf2?BS z>EK3lP4V>0aTq3WHZT7g*^qvJtwhv9RTq41yi!x^@C1nOH&5aQ+sWwiwk?Ir(Gc^-xk(n1jjlD0(nLWKwS zmN*;pUwa6ZEX8i)q{U_rHHkP+rpZtz;ddB0gK=)#@dgazQr-UE?nXaBZR*9go_5-4 zgIn6-atKkfmQ@s#(W+foY zss_<$wq{BmhAkVi0IK(cuwA(bX@@`~Kr3GhQ{2aXhY+i322E}~-eU%tldsCBoJ-0l zwM=Z*W$f1H{0YsG0q&K5D#^6~DMDpM%4}X()o>vrXcfNBp~3%B?9!nHD=4Z8aQ*mW zVlWg}Yh3McG2mgOtIJXOUyAMzqb59}4F1g5d4ZU(GY+V#hQwthSPn*wHRLfEYK`LP zb!!=qjWG=(R4s>#3;2ClVL@yH$uYkIQ9|Yw%n!sdSCrtkjCaT3;uU7X8DlMGB6&m@ z{jmsOJg%xTl=CJwvuiSabys~7o8fsRJ$w}#lz6&$75g${*em{4y2~R+{FNq@l@=aZ z@QDqwi=NVNZ^ktUm*jDjyTJ>=(G1R{K!|Y->bbdOxvtzB$6s%Wceyp@taDx;-1GQx z54dGUeK>dnw)nb|Dz{d07^(`~xUP(0QQ7Dl$~{)-jHJ7?JvRWHyGZJn3(C5@X$ZXVrz8J?t$v0hDfQ!d0UXX ztf4xNRWcSAyg3(s9Sj5e2(_3`Ss`bvk7bVgp%`_x4dvaZo2h5v0mEI|LcO;>!be#C z64;n_R7Y83gWRh+s`G61;xIN0W7fUYpuC<+t-7jOPo7>LT%L0NV_H2C7f&-kYlD=h z-ZPK6T(i7hj$Z7lx}>XXvpnxIJ>QY}lyjpFJdJc!E6^$3CT(NLOsbgHI3PcB3SjZ! zW>vm67pADcqoY~(sLiB8b8R>EV~f{!0D$l4ksfMr=pU#--g1_4bw-Nw`AKl~zV#gM zl6t5Sa!dIyHXu)`%2dkgn8&W<;PmBn7m#g_2` z&H#)Wgq`3X!U^k=zAB&Blp|2tR}B#%sEUPx=7iPWi7KUcFgaQEhA-%CcTei4_GLxL z?*8gnV@rSW7e2l>K%I|l^YB}ORGW}}pz5$-`^yM2VW1i!Pt>qDj9CR0UL&(#$}#ml|R3xX<5KkQ8p;Sb481y?#$hSHq}q z7uln zLWL$AmP(^k7J6|WrH@kCp2~e5g``h zmadf66ebz_rm30M)<80u>MCy1{!H~Id#HMMhPqLjD+F@n5HLr(AW+VosgA=m{5ew{ z2@QPOqv}Yj2)%-7NumvpsqH{tPd%o7ZcPfJ zH|DE zUj6%Vb)lu5F&c~2U632}Sb|2jms$Dg3vKShOVo)Lul3l#V`noIG^tEL8j!kFy^oJ+ z@zj+pRrRAiZK!iy>?$rS#jJGCh2)UWEuolb9VJ}&MCQv&{)VG-b1rM5vu zc|V6JG;WnT1v0VnRcdRgJ%{M+H%RVMVI=5Ict#y(l^(e2($27^3YA1a+qN%HooU4> zvaH?^BUhXjcAOoPzY~^t+i`3RBr4Lq;yE>z&*APy_yAO8c_-B0eQ>qvYqOs4$-nt! zn7eX~YPWcG1?}>s(r;rFcf?v?uoe-(^n7uvkK+0kmzj5aO0K>*XQS4It&wA@7EkK6 zSXI*XTFuOUIVf?K&whNK?s=)R1SsV-n#*G0V5$cs(<*^;M64{_n?8Ww807R&EUs2sU=o;kCt$qJ+hu1PWa{T z%3thuOLzVEsMi6)uvx)6aL;*NEoPdMa~-O?a+ztYT0l&FJol1@! z0H&4{w?o~*c^=O`lanzJo!3R<#w$tg_?_x{>%VbU{nMN3Dz9t+lARKFvMZHfR<`fL z!U6)>rN$r-?{~XYMbeDsEYt9(h}~*?__vmwD`{KD?$rwu3)I!E87!rCtNn56Gq2P? z-0xvDi|70H)e`iUj@h@rrQU-PxcHXZO;3PD++YhJ_;#!La>aC@^6wxSD(nc~D}|k5 zCK#~?I2VfeJ*s4wPQ0&%$wAQB%A!563@F?dRmD6e9Z*|P$sSerqQ*QqFDP!-@8tKk zI=l%(5!P)D>c9~Cm`70@Ub_Z$c5X`*BLBD5<#IG0p`Bx3f0@3TeO1RrMbZ4d>LxTj zEg=L}r}g5XA$>2UO`+1s)iDn7;CQ zZcb^zwiv41X0i48-|NyqQ+SUVKb{;m7BnZz#C~(>pThMm>bf5d{sR|BbXkKd8f)(%Tp!~ajjhN*T=TF%=YW!ZjH_!1e0AY! z1qSjVT&HlgftY7M=JqVE9cX(O_%VH=F@$R!Y1?7!8D#fJoMY$B@lgF#9>z-TLl>I~ z9kKPGi!sn`rMHI(jG6(x-jwsO;3>|BHm>pr7@xj6*CaKc-H!tM^^@;Hgy~*;R4uTC zaRt3GUd%lu;pz{J$mxI}8d#<_#cG%4-??RKZ%AssE>l}pIS%Cc;wb>mJHhUM%2iw7 zK)jAGR?&SH3`A3(a`g`>mBNU6z<_(;XKEMTPtdAks!K9*JcT@co}6uf&e;}bK}T3| z46`#xmkgx;4!4ViUx32EJv3}MK+wO$c6egG;@g6|Wdhj$Ud8TuU#Vdh$r5&Ep{-&` zHMq^=YPK`Y7?QzAxxdo0>ujHUt8TNtR>$}Zsk&Y8jT%X*OE?zXH)xOV3Dw~Py>91c|I6P$4;nie1=!$IlqC30N;jNM(dPu-?u=oWAqZU z@rAay()HU+;}$w6W{4dXDEXlNyE3jB=s|^=Z1ovyG{H_8OR%9>aaN6LJkDq>6DVd{ z%_j1I>P@5MuW=qAHyXsC@~qlM($F51(muQyRa^mYnd;pHLV$B>0AMofoZ8Q`K<`i4IFev$6)s_6S$=RVkB6fcd z3WaU-_v#Op2|A3F{2+@%8ZjJCq)?(_uaiYIS?96ctfV97)ktR<{PHu2Xod@;e%C^` ztHwf!Ictsn@V-5f?-kj?m$2Y65rn<~4P?G*&WE9X?rO zvJj|pIy~eQUI$O@Hwh29hkBblcTbc4Q3p#Y7J~~9gb62%M(dL^%$1R=jeDNREI>L5qA(p+H?sh0C}$|Aa2|Nf0!Rw1_?1FfQ`*DPrF8<1aLNSceS zq6`M?Id#NimPd3r46up&ARv0gCdMLsP`OR;Ssr&iFIbH7;CllD8UnI|$v8r}!du8g zM%%rG9+4@9${Sj-&+rzyW0Tu^>26h51X*r5_USRu?x}X+(v?-9iyos)Ykfou)PBSV zZQDzU^~B@`tQ+DDFAw_EAorGf7(toIuX5(JAgbpp-iK3)oeq{x_=;4?*5u+DbU9Xx zW~wjCWBkN8soj``2RwZ`n6GRI`OHZ_;iyqlRuKK|CpyYgMrQektKR9;K-_Ja&h;tv zOwtc9yoN(0Mss>K6l%E$k#b`)6aH=<$=KpF$pS^ujfwSr2 z!Fu}Hx;8kA3|-cJjfAfU3z_z$6(Y?>B0#du1^&V%B`P*@Ugd*1Pr~S`!XHm((1LHY zW=%br6H}zYc}yF4ewaS!%ZB;}2p6|?Qh*4Pyqd}D^71fI7M`yS5W^(asKX&4;ce-I z$bf<-P?shIitYv%nf4AikAxoeL1Y7k+_SF@6bs?(w{Z~0SZ|vw3I{X2A^lF)U|pFV zBx3(Ra#M6PNQ7a|ehd;Vx$R-W0vwhJu(mzgbO}ILBEEJft+@U5ato_BR9ay<{t5a6&T|Q( z8^&_0UV>(xzWwoHzSoZux4U9OTjM9+vOMzkQMg5V=^PD-N=1yY$+gS-eqP_q98^%Pbq{vC*>3p}cLv--{tpBM|~Kin3UJQJ;?0*Hwc! z&>GA*i{a(|uYa7_D&;>N^|SR6O@-7O&TA@;%6y3WCPX!pAz6!`1mVbTCKmv`*h~zA zzoMF(PADHYVAGlU1(>^pc;Qi~UDSF`J>ZUV@HpnxT?;^O!UV5^%Xvc;{ttIDju?OIRNB2?6O98{5-3!>yw~ZJg zrS&G=mN9P(NrOn1!}tiS*cJ(m-H1Srf|r)K>JhjH9+mLaAl3 zNfE*PB(Xx0j|eInuC=D*b|Rgts3Ao<+D=5vLh!H0Vd8VY7pmO3++HWs-SX9tG^V#V zNSH5``@n#yq&>hQn~t>CG0VX9q7{{Nf&8X_2Qi;(lsRQMAUbvV#Gc+-a(iIo)T+KQ3EGLb8;gq8V>~__a zbwD=Xj)T3@JlNN<(JzH`LX-U{O$8T|+zEIUKEpccT*|yo!X-yt>N`BXkB)5bB%=_wo@$Z++fGLO+$V++KEuX;=5NX0lk*u!Ln}H9 z8xPj^oyB&8LEvEVcbeT}UBn7T++9Hcxc1)oDnlcG8HZ+jLG@VJRoDX`$D-k7Z9=I| zj^FJnmT_f0lf_c)e=k}3K3P1)<)^2JRd6$6xkp6uZS*~2@KCPZgl0w_!;IQ$C_9kn zIe$zDA-%g@iDZg_P>~r0(IOVC9FSmI&@MLI5=l8Xp%RjZGFA}pF&NEqAMp|a;%{;T^p5+*5jY^ODXkoOqhv<$0W1Pmo?cEbB*j#$Dr^IxS zF$B}To?3oPq0`j9PaC+q^httN-WcV@8jRgA#;zeG$yz;n%jG*I@@_@089z!s%ZkS^Y7K3UbqVCTIi!D~mCR#95#K`A7 zejaVXb_OvHhYB`uXgf?SmNX!VGTsCam;E#_P+6gmewqOisSTm`Qu1(Nm(HX7;4>sP zykK;!uTK@Ex)%%=F&2q*%tclo^_g?njdFtFedzdo;-ts^C-E70?JVvCM0b5FPSaH0 zFJdj$6+v`!G?)qOZ!u1gakWEYS&a?sg;6^Cp7eki#wCB< zrbFM^2gF{U*0rNWU%7g8m1n^iAvKhq({yCo#Oi6fq9O5JpwwAQ6$tG*TzVKyC1lWYlvW!W1MwBzFn;-Azis7>V)4 z(=XqN#I8`a7mNonfLpFLc%^W>SS^PUcFZC0-H`kMPQhfJgV1Wq1mP=1i3~st?+oWW z;GPJe9tjt|Qh7*&vT%a1`{f#ZAY%u~B;Y6$Hs=!BB&I=+@j`LeFk8VyvEF$CmX0WT zmx_y<3BA|aNH7iaAq+0NA0Fn)CW=nZXgpzZ#W0bCD~}pKEbc`gvK|(_?&KTh=)+>W z^x0!}zytx9lT3mj3S|?+KRmbS4u` z+@L3~>B&Yt*`z0%^#uM9xa8}4vQB)9I*`X)Jda_eb-q4dbIl*jA2gcY%PfiyK zPI+wRaXwDUw;p=Co$F~^zuwJ zuT&;J?;9h5qr16K%~#IEBKZ$l9u>VT2dK}ZVlkrq9eETO=|d`=gXAMUIjARx^yFhb zLBKsOf-rlW9N`3dxNH$ihi79tj?$UgVj6gtG=7Xwd7PB%31Z^$9m3&pf^c~JYW7^n zHNT+pxoGZ}dh(T?9One+ago3ggN2yy-1(^BYs#1h7(Bs=tQav$9}@|16}9s*F%qt! zWO7PRPIJT;1K;<_fnyg$T zR9K)nv+=?&oXAcj!&O63wipgi{z!0GAxF%I3Pn6F^5H!}CW!RKcYkoQh$b#XmoD*d zC}(oKd<&L{HaOENU(TK{V8!z&3j9@7K`g0LF@(iSkb9Ynb=5QC$2Er~?Gr$SSM-<5 zh9iz@$rF$hU4@Zh8*ljEe=SJQvHVSbOVR9Wdh4%OeLNoaZussE{z5kjS%%*?Z*9sy zdg+8qFlo(Rh8_4_!E|~VD4r#lS}YSuR*0CVE*HZ>>wu%=m2Shu=!>x?vnn}Gel`FbPN}4OASBqhJqLsC7Fg=wgq&f>*!6Z^Y zhqS=)EWjAV;aO3omXqL-xGyzOIhr+?~YWJ`r%LrNQiK<4TT z!dCEtm{`k3PFME70M>dXg}x{vWng(MS~(dt=9O!p3=7cclov$>P}YE#u;vZ+Bl{)6 z!FQwv^YBaJIWHdoa|C55vHm{HOX=;(StHo|25iK+S`M~bK85UT&&wiJGPFY}^J#L`o+9ba*ZB7Ccw272%Rtn?q^tKtbaN`y-6+y3hnF^MQ6bw-=b=+*d?^ z91|bP*=hqiIs>z(;!P2VulfpTqC6DSg8NNpdZ_*e?4?`=J}b5Wt0atv)Fz?`+>!(- zAgY6*Hkwl;*6^wu0f#ntkoc-tCl`mg`0V%~LwofQTzpk*lsuB>BIs$1P}K&BGLj%E z%I$|UP$$=kOam5QL=``-hd{>UsZ6EgTngPFbladdba6?9f5B{M)>AhK-G!w&K>8%` zjJxM=5Sy5XW+qSy*)eE*z94m@uv_Z|(};~?Kcu&zn?!hMeM}`YT(DlL;tlm({(wy) z*vHp+EU5GzIPgsV1FHMnO~7;TE%fUqF%@EvoW&Z>T5T566H<#UqNA4uD8)h<=j#Uh z5x;rF0KI& zJ7dt`cKDb%MBH$m1-2SfUnozeNLMxVR`6lOu_gSFb6?H(Q5K?B51Nhu#+xsjf3r#4Pd`_eLE;(Df#RW(pU2M z9Xcjly90QyVK9BX!vo)SFNS{A*lb{KU~OJ3vYT)*Vb*&6LYwN(u^+rdjo4wxGo!^yf`-#bG3+T8Mv=xE@QB&s~F+1%!t&V zhIQbus6kIcVW+1x8G3q9pQN#-m%T~34py@Eqv zaHA>ikcg~BenX=VLBIJlJ$Xpz7W&)fh1!6DF21u~q%PeIk8-TWtS>1ovXYwu=AJ;IpxpmctQ~9(Q2$A!3rK98)E1wRw#NdJuB{yzkrTiaz^(exN)rHuy1}T#{V13 z`GsFWAs2YXn-Q@fMJ|@{gR+tGV zCQO*v1-<$HIP{H(55i^f5wJ&JizRSEQS`Ow#=ZUiYjl1VIZudQjc?UU*wHyg8vOY@ z_oF8uP{o^#PhwmD6m>o+T8`!gTRnNzLT8qtGHi{<#c%(c#S9!EH98){`Tj{!&x&*T zMKd9&59S0g%13-c^xtLQ#vm@iPl(AD|E8j@p0vkscKZfAHVheoWq@NS<{GnCn#P>d7#v(jH3;v4@buV-BIV=g%E@AdG0Cn!Cw#|$twJ*_hqmP2u6AtwG!o=g%`c-7qAIQz9PloH28|x zTZ4$Q+`#Ctb`=Z0FO^>g;Y`1Z`MyATS0TXokjWy1 z{S$%{JWiq=7J04){~7)NMzbbU#@`|m_QTQ&d(Gb>m$hch<@de@%F_@hej$=wb4_%z zy^Ztalsq2(@Gf1$zHKmx>tc4G9p}ioawbPnRdc=Vx@d-`etjKHJwVPIP)sbP@~#2? z1wUz?0^yxEAPJpw1Dq;aa0BcVTxeGvqj~j)=mH0cXKskG*6*&+=nt`QM%@&#wl{HX zzF<5KMHb$~o6Bh1O{_Z{6#6;HKVN+dYxW<}hNo-TKO#x$=FL&jIaW67yG`RZ1?~Tr z#k^6p3Skj{?f+SoDEITc-!M_>+~@N&-3OW6kx=;*7@M-vk^3c;dKHs_?c;X{-{&he znQI==8htWC(|xKZTeOKiJfWi+u&VWZW~aHFT$yOat@KgQ#f)J80;{%0E>^1+Rzq^c zSee-p9cB^I4$;n==&~A|aGBj)p$gb@xg+Xm@fOQw>SNR1k%)lthagL_wIy}((gNgE zncu12To|Tfk9cW!Lkzpw3ut~Wec+{yf%v<8C0Ln~2ca-X_SU4y*9dPd+5(j??3*_| z8{r$sLLtUg45Qs}@jN3K>z_fe?pqC5WNwGKuZi^XFLj4g_P5xj+9|EBF9He=fXE@) zuGt~AzIaOWm-da!dhs_x^Uw6hLV`oYwmfQ#qBnqh!ItSR-t@4^0srCa(ma7*QirPW zZ&MHB=ubJ%D8cUQ^|VpCK`a9wV-6gI8Skt8WZCOZ^V7On{*9r*_6FLk0ED!LTBJ2P zm}WK9M&R}GhT5kV?9+;zn!hE6inc{6u)8na78z-Yqr4r!WvPucU-kjOSunD$%8J*s znp0M?=3kHkE@*WlEyU8oqex3Svpq7B(%%MzTyLZ~0uzAnV$po&@)!bm-VhwyUkh)P zh)2u-@={_rZw315ueoG!ua+eGx%_3EGbyOTV;+RoRQeVgD8tpYkyYhq!zaT0s$0NST|vK`^*Utf>$PY%}-aP+Gh zPW$Wc4A7H-oP^VbaLw0ikQ@pQQ!GE8%3p2i?jHg0v8DynukSd*sIn};)`0mpCSnYi zgYWd<-a9=Qa;FDF@AP2UogNIo(}Vl&^x*zGJs5GP2P5zFVAP!+JaDH6qwn-!%$**j z-|0cdogO@Rrw3y_9yIox!Eu;&2Cj#UbUfw6f`3bo)$9!zeoan&g2xAHfWX8%J$U#| z4<>m$Ajsa@TPGt&Xf9c+J3!OMSu9hk+5w?^Jl1Y;tQJ9zdGKDEUVww3j;XBTkHo@D zpp2j3=rT&%1%!?$4hq@V2St&(KFD6sM6-oHf}Sz`<|XBcil$OxGoz<2?z$0dK8jJWV9U5qx{d$6VEpr{xv*CzqJio#{1 ztk>oopS#?=c(cG24$Ub^a?ia5>Jb`TsqrCzaz@N*u|nvI72c2%Qe3!*}51jxmK z%BqLx5e5VQq#3f>MzaA;zS~seLm*jgu(OuKH%9}d$$T5_MFAOSlyR-eoiQBG^O&sI zfvoUZA7TVa+xHws(1;WV`|Rn;##IH zq|sSytC$Nl`Pnb7(5lv25@q`}*5eSHqcP1)Jjr&03ewlI4!UKN3 z+_-0sgzuj;?wLgM{Zqz0qc6UHnjTHiVjzxqIYH}XUEzUi$TtxSZ>48WNL!aLjY`yf z8*c`;&1@M%)hc|F(`Sq{*JGGAB?2(=YC?p=hlhgSc-Eu0yZ|V@3^D4{|FP?fI$wWW z*i2JlA9Tx7P1qY5KxM7KQ^97a3RihR^|iXb&QEc`)N|b5r^MD;Kj+3t;l?F1N#5N#=TR-j)7#o27u#+GxQ(WORJB$6{RF229Hf zhy|#%w!BErwpy>0myDq|r)rIHZ%)$i3!7i#{SXgiA(gi^ z(ZH3qT1`w+7?Q!zi=blbD?C%yf# zl|9o=i_{J^S zZ{i;K)CN7&lum%%U3`yDF*TR8m&$p+S=dR-b?(0H874t-zI9u67H7L}%P#7yjdkv+ zEgM+8LokjXcLBfgHa*fsdm6iX(G|PIcl2bRp1i9k`}O2KJt@(XQayQJPyVAP2lV6v znRtDOy6aPU14QG?JOtWboDs*)!o7VPeS{~Tb9*qD8pL}A`5Zz%&+*4N>3|jMy{Xw22n!{glP-CNmXJXOfj*al~j^JRY^f#WE4~_F_kkV!Saji}CMUzV@k6 zjF-JxEaQ4U0nJ{&Y%cdaw8RdCgkF2 zoVYuuK|G9GOAnYVO&O|%Q0B0vA+Y|)8is(y?LUt|l$4=hHo>b8g-mWGH6EsgOMQML z5)VVsT{eWBJ`U65A?$_2v|%W^^B9n6a_=zT{Ospo7Sgf4U0|@PbYlzxQ*fCwifZxS z|HXl2%5Y5&iPjQt!fNG4G$L&^$H}eS;hKI*cDOd(ITT_!Qyj;=p5qqxY1b^4Iqt?I zw7M3{=k6vWwcn)a|2tT=@uRWfUP%v(mU2ejs%o^>UB7JnS6sT7!MF9@jPmdCY`b4cwEj4Fw#El_?{G+H)gaEWYg0#xFxT)^M&2W{T`YFTM z2$vmxCvrxz%gBepq4`kJJ2)-b={+kVzMO63o6k{5OMY)?mzET5&?4?1LlF0cQ%}>8 zzPOJxBft!pq|K=D7Q>&}Cw`mz$$y*&oAGX;G31!6>0#Qs>W46MC&EZ@#biwn0cu2B zESU_7iCvf-AaQ-N*1Lv9rujk7fwLHu0EJAQqBWJ+2Li7`D=fqd5on}j3c&H08-}AV zaYUJwQ#BdK^uwu|dFj~gnio=)tw`qZ<%^{8gABUOoYD61}{OUV}_5r1h8_C}1@ka-_=krU@= z6TR4}ua&aq!m9Pc94*@#7erI%LJ&KL4$akGm(DVJpo6{gcTPu0)Cf$R+NV)G9iOM2 z2Tmw`3{Avo^T#wk*8pQe*i@{r+1%OlwfXE7=f(mp64ugUp*90|&o9J!IYGM@B96~W z8n6gFYc%C7(ppOKxe4AT`s1YuIsV&Ns+n(i)n-0-agp{Fsy&n~m*J1uS~rPDyP&;1 z`zA7mm0*tc5f-D*;~GxEf5X}_UcPxNA<5gf7!>y;U0saEVDT@(r(jOG1kH}7tR-5$ z<&@j&2@NXoakOoz*6R*dj=W%d>_MFjvrpmT-~Z;CfO5=uGnDEWleJN8`Icdf5iBnW zb4)l-s*{k%$o6(cmg!n@|1xM%PSbbG(35Y;XE|_4wDGaANVx(iG)ISoOBC20ss{{4 z_Hv*%I80j($tYJ9NJVQPQ2B=Ku9oULs_&O;dofT&PilJX<3LL5SJ%HF67q{tPiavg zJ~>YTCqv8Re(GuMsVc`#%bH_3G{kN>{rxb=0#<6N5CZ3|)HsSej>W+2yGI3lrZIVJ>&yma`oFWBQ-)`H}ne-U)yZA$qIeh$@_w8OQS z%iefN(|s2YrHps61}gL5=plQJcAs2sLn$$uPdu#AmGeM|e<-tsECpkbGD$)8r%kx{a;^4Y4OKNt8+eljzM>_; ze*fa*0ELoLV4^jz03LkK83TF3U0Mi^1qTtbUe(@VJz|S>S}QarW1ZHIZ?~@l;`oky z)@#E#cRjN=Zs!K=AKhE#GP0yK1PgH}HiFa-5xz3J!V2f|3ZN_X*;qivMle-#=*UKG zF_N@RS}*7KsG3=BJ1!O@{6J~%V*{GK7W%^67wxu_Mjos(bPn)$?a)|v#I)L#%WZ_(*Feg=LIKnKw_u^@n@FN5IZ_oO4hMmQ~cH zGe1FPqn>jHDHvZIxH*FQ~Q#RD~GVf>o35hAEg|E>>=|rtpfNd?Q>uY z!y$d~=h_hb_By7$&Y0_%Hp5x_g7nl0PsDaF{R>T%K-7-69ST*ZLi@T#MP#_*M$LR_ zt6K{o$9=G22XyW`AYW3++J{JxYgW?+bAhBizBg29{EyRCM3&?l1w6bcrT+r zEGue;i+Pzwl(9bw*0$XcP@}97qJ*Wt0Yj+Nue7MZUlC)Wb{^kEF9lygL#mUGi(lgK z$lRWZIlkBq zf31atayyxPaU;0r+~aB-XV@9M`!)77bLr~WTFbx>v301u#YW*iCm@F41~Yo$A>mJ6 zrnx7yyXA(+8(zF%SygsIi>+ZXQTs>DVbH$Oq;>D;Z!{NpKK4As=xNJ0nsk_T;v3D= z{cOr4;3LOLO%Ee2VKBe6B{1blDZD|jL_qLKEw$bi0~6y@@H7I4)Dy7tJsgNbG3qG@ z+$wDlUfu4+!szJ(r!+<4Mzg297vkRTrMy$H#n4S8r12x}5v^WQhxud+&uQs*BE_24u_CMWvm?{oU%fTC%kUTg_l+0xyFh&jbJI zdGyp7t%cmbn9u(2<)Nyl6r3wDC*$TBEn4c4d5xIs#8V4(l~T@voC5ux1#$hGO3!MG zjRvQ*fsI@GayYn1Kc|J%I8n+2Y zdKzN8lJB(Qp*$!}@tH_mCRfIJzPRTx;3{q%7n4kJIdeQrzDDNZm{oI#MX&xJ;=Vkt z%HsRq=W;Jx5cI-jUoZDrE-EPQxFNW2DY)-qS!tP~X{o7zrkR?7D5IqYre)>=XJ{$ZdagF2GF_{D!<~wGA)tT|=|%9!fx+>oUJkyUaTw$`XCiAfugJS;^s^A4QB?iNV9G@hmw2jhO-~HZuo>& z8>-=KTHW#2hn0;4Lzw)B^9o;P@t7xG({Lx>gnkbtPW{tK26A5c)A=JeJ@=11SiyO` zrIK|Xmru(7awhYO`lFDsgb(k=kB6+m_P4W`tIOU4KfJ8;1w@m@gP}_G+22kZr{_mm zZL9@r`34)5Mc;;&o9z~kv3Z3oEPlK*hD{!44`OLEOxB`1z{>(md3dG(7Tj6(9cTDm zNEC0ncVlVCfyj$@KqtWLx6mnZkP#e**~iS~VT4_NW{qm;yF09Ob-*mP)pd|7QVedV z5;5?T_br%=I@&UA>;c`Ug&U`exSzOjzKC6|T1LhRn9a8dVgiV>iy*c^UR-RKH7tST zfq8=1pNqkUBR|k5*wHQ|5TNY!ZDwz+C?acO4~T?lKGNqQ+O_bBpXK!eKbdS2hj5kb zr52Ij20dmGxm|@+9}#bo4a0Rw2sM&9i2!X)ls!NjVMNOA0zx2RrY z7}}UQM<(O7q}6jtx7|lfRFfi&kEp)v#|_oubf6iIkTM>{*?YDXv9OJ`ii3ILjV$m! zFZ&^1F7~)U|q^n#8W^H=NpJWkB?L(HmFE z9L;bbm2yIaAZ<}hFxn?t5iD}qFU1}zFi}XPf zy&y`GRG);kYc94#v`Njy94!Bt!$kGA6Uau);d#69f#N!oZ#cV3u3tD? z6eK?9+Z5T-tc6F7dqR&n*)Cqm`A;l0NgfElo$*l|S_wR-C1QDuacG_UUvX&N^N2Hx z^Y6xts8c;6-8Bvkfd3VT(B3FcVcu=J9vl%OJ_?85w=E74-^Fj?k?=Mww;&3yn}v$% z!;O7e^*6Zwn;a$vHwe{OSv7d%tT1r_5~)T&=&D*xmWLY1VoA5OwGdC((BD5S!tA*Y-;Wa;9YGVQk)8%N5?)347;Nt z>f|18^`jObOWeqN7nf+$qD4}4N0vA@h!)A*GB2+pTBKc#{##=CQKH#55F|htv9ZiS zWKZ}PyS1=18w}1{kT&MWh`A7A2F8j{nY0~g=0&WLr4Ee#TvqZcMo)e|7%OYMNG8R& zM{@n|u)_Q}|HATiX51^|(`WAECNq|HOcx^e4sQ4v((p4>9hOx-Sh}-%5t5u@uqBL! z026+5g;~P+&)R!^!YmQ|XW-M8FiRx=S$)A3j!P%4+xt4%NvD`)iEc<2(~vH!X2Q$!JfSV!fempFY@aJc@yVcg#7F>+h~$a!hVIPJ$0LJ8gEy2C)=T1C6CRk^ z_M%rLc+tw=U@<&J2C@k8ib!(S&5HPku+UxL5+61}&UL$m_@EF|(5J5Md7HA#YbLvZmyS@L{AmBiuM_(s2GQ3fd?Zw*<;cYm1Bq>5lGsX^#d;)(Vf_w% ztwyAM3ss8#cEisT-fn;k4De!@I!y3x$4)0<2&A%VDUBZZVlB0fSd{jEVI^)ke2 z_EU^^C@y8RZ4G?w|FW)b2BLTtyBvO=@DqUj*qmUTF66crtwEg(;oe`W)yRIVxs{!7 zEe1y{L4oE0b#+$cJQtsi_1BruMzovok{hR(7925w>tTh?v%E!YTpKZ}$90cdk2XZ< zZGeLfu!)tSppYwgq}Vg(j{)QTmLj1&D{TfbK}`T^oZUeVcXvp}N^7Y=krK;ni>_{m zsCfDLkPyb6Y%5AFHe76MkUax%Q#6ezoHH2=3`l}H|O;tN$RpMraM1Q#)(o!B3G zF9X|&aY@JVkg;d|asU%&MV&{PQ3p=OQKB24z|x=fwp$M1=Y6bpo_AQz1Bgvk(6KvQ zgK703Kgz+SmEcJZ$B+eu)8BDColG_G3=bdOn5JLS;^=9Z3dh#d?HqVeLyPd~m3fy< zZ4Wj0J}j@j7={IVb9+(jn|Q9FG#bM6cNL}GH?FR39lq!B(W0woGO<$4_yrHYK1}E! z+Pj2nK_wnRKUOqkuhags$dZ2RSq@_NbP&S=E#vFz22E(d!#Xy zrUrl^KGH$7_3etdVieG#}CGu{n*!bQ0s_HzBjqsfb!me~%*SNBF2%`g;dfDZs47 zzK7PpsHhiSK)NW07Z%SBXH{j8jYq!~6wPMNG-E(^!6KLvhPl3UFqHOB4z}O~FDBCJ zPV6i$Fy)w#X(GP!_tn)^t*op2;wemFtLo~i*VNU0Q&?Ab{{|S0-&|LB@%g&Ce%tEm zCKcD!4Scb#F8rmsy5xOzbyHuftJ{Om|3F<`S9~oF*46dE_X56;@lAYPow)So6OR1e zRdIyD*|fg#)$g#@UB#9I`@GY*gJi%>kw`~)5MVts!bB58{OW(Hc4cu&+EujYQ~>mh z9uAl$1wFejk2enA1DL}7wK&uP_rp(zss7yzXAwHjXp*4CEU%U4`S#b zF)0f_iF+V4kH$A1AEC7mzM1&YL|#yXKuQ#H)euHx^b(5!lYRLJ%CylLE8za*2O|L3D;1AvsoEUfz+ZWHXZ02<`0;yRaf%=W zx(oV=O#!p5{l)fhD*KC1(Ee`d0FfJVcxZswnwmQZC+drTvg5pefXJ;7`&|?3B`ddZ zh;17vF5o5{0_)SmLE!QxFWtmvki?oA#7 zCMA)@Y(SyYhKOl=o14n!^p1$*QtNcQ^ah(RU|9lSfJ$Ds8y3@vK3 z?<0eTMVs-ebM^_W=-JQVsJ7gq1hZYk#4NPE;cdtaOOVywJwqHqS~pJ*7hS%sKs;&4 zHiA_?MuPw0d=LKTa3E2^8?0hy-$X4&IFI4pGeYbjNK8WwX5~!1n94)2*B`CZDU2A09I$6EUf_NQW;}Ke^cvl zHhHXg83fQ{9N(VYKMp(LHmqQP6vciUC-wmnF(5_v#POn;b}>^Yh%QrdI9okI><6%N zf_R@s8>Y75Y}Q1PzXxz^q8MvxiB0cBvE?Mf1I-`t_~@@6KE1s(n~^`^+DG%(g`fQa z)0n4l!X2d}d{OiC^y+wLx#J<1%bz4(q$=Gj_GEh|i_@vL!*ME8b3bim?-Qr7{3)0g z;G4yp3I|e_ERoxTYBp7Dhqk6q6+3q^R#-3We^!=FeKSH8CL8J%%>3`=QUz4*WzTxK zQ7=CJ^qPJHso(Km!K#xqdk|Wxx1K5iWt;~@Rog>?P8q77{2(^o=)4ETG2A4rH_L2g ziHc|!u3A45kcd!EiAh`_v9>#)+It@s2b)Z9-(sn=#X&3_FW|E5M;w^N7GhDznuWEZH7l7VJ};E9 z9A!`u z9&^QKk=vQMV*hbOAIN}rjV=zO31zyL8-K*rG^m=@(Qyz=80kwWv6@VMe!PGMd*GUPpon<IHjRnvFaSqTgTAdZ_$XF63F`)^(-4~UXY^#z}?rMt#egHQYvn&o+!wWyO(|hC7iT%m;|3;OV)|QxOzvUacLZ< z?(6Hs_f7w)b3Q9j*ZPLe7{>dm6)S6JiYn>`1*ARe>kn&6TEy{(gTSQHN!_?Y@mbyz zU5#w&QyPa_yW9k`4aXqghSJssY+-3Wz~f#I;an*B4VcE<2)Q!R#=~g8$kI207HWPC zg&EI{;tmt_&hF>MSZ3ZN_VMiq#8U?>VEhrtPW9m39)av!A8L36GQ~4s0z2&mbBE=d zMXPTYJ-}VLS@aToyXr6%2hQL*@vv4O8l%j6i`a?a)GaC-vu=y%1T~j!!FB=Ot+$Gk z$z8Wqq?ci60tqFWolot=*D&v~PqvD~IlBB=-aZ&21(j?Qdt=>Pu}$Qv!^gIX+i=C7 zi^XfExU6jAN%h(Iq8G%6w3KCo%yiD{jw}{Uq&fw&cckIKE#767h}^nLQHl5$9~x$y zX-POivqN-nWV>iXz0YhHU#0pkdQn`-JA_C)p5o%2-*XzKnrdr@tnegbr)(gMb|lYy>8_9Ul(nbz8g|^DB|uG zTh;GuWmbJJrlYJ@*i0sGaoCF9j=`11y|@#ZpX+0ep)Coqw)7F}`_I;RsFub5hMR;{ z0`Ab2z5;IV|5MXAO@^?%=dIZG?#Aq#%xbqnBcsL|GXSr(MhswkUPbLRqaWQ_d^*gD zRJDk-3a~F(|2x&=cTfJiNP^`D|3`6Znz2XJ@5fb^z~XH7Yzg{Mr*M>7z6TpoJU5*V zBfg(7VK3$!(*40E9QT8`uAvJ^)R(B`tOx8rC={cSH>P7RM5Fnf=KfCj(lFK|;zC*e zUJz-zN8NgL|lw9d{rP>+o~8H%M92gC$d|WYiW}{$zE}&Y^F~D=f z3-`5+bXUDeM{6`mv}Acl!T;Hgh!ep(K5|5C%Gsku$FPg0b>}IzwE`;Rr;myG#GXuk zTRe1^n+tNe7-xDEjeX7x(`@A;HxIV2rxeM8kBiZKYr_|Q)Ch*aJ_FyAaa>$Q8Ge3T zoMjQvZ9Z&j63+EAav>7Ji)gd{C3fY{x8ZEpD-O&8bi>>g{}M}8MaZr!Z#t=9y^CXc zs-}ADsxW^rgj4To`+}jY`fzwy(R-r$dgct4_d9Jwaw7SjYSw#DGy-R`?>&(#(_Vg0 z952k{+>jgkPtk(YXyKApOq$?{r%u5K5&63JMQ4sNUa%IAW_UH8dT>qr8LC>ZMPp1y z@hN{j&J6t4(~rh)2R>S*X+J^!TKc$pK+k|8G$eKpJt+?L0w=Te6vi1Waj4FvQ{u0j zS6GSI*q)T)j%UqjNZ3-?rMc0#KWW9S<>)hF2KCacGot!NKq4a3nqtD&4z@z0(S)i>fafB&=U-YoX4sNQVT{Ikw#eU-ze=3>X1dloYiEY&QIeXqKK6+wsjD z>E6L=QwStlr_W&mK-krDVk~EeBU#B&*s?2Wq)fgNN*9$N(HYUVFsl1GSsyeq4WMQLx!%XL~gNV;_qT@L8vydWR=_AaH8i zA8O`Jr#jLYA-N7!#*_W^IF#teG9Sh`E)R!zrT7!|kYrzWoRfX_iCX&APt*||`KhWx z*y~gAF(S%0KUI%HE`KU=t>K{0ME;7!`p?vOZ+@nQefjPw7jM8KV{ ztj~$6E{Zb|e*Bt5QlPT^aU{nSE{U%HaJ`Hjxr0?I?K&ixLoSIDlFqpVX(vircS&vQ zu}k8hf8@wpuxopB6nI%Q|IfS&^OsoN`IphXl=JQ?u~#GQdh|#=CF%?5ef54Uv|8Lw zSb4Kr9L+cHQ`l57-p&%f67j$R;!VUy(?)N6G@6O#h#VU>K!%rB3-&oXGk*t;o3Er= z`~&{EK}pgFhQ49aVIpH9YhQd+bT@q7EO0XT&f>2{e{JDwJJ?G@KbD=L(Db^9FsCV^UWB2|OI}SS)G~4qtwRnfPx%n1l?BQzdl& zv;&&^J2>$REu^kViC1akcJGcmP_1r*5afX*8zV~k8$_?qGdam zB(%6@Gz}ct&0j>ayu9RB90qXB#5fwFI9cJ+@Ifd_pL>aLX(kz<`RUz;)0SVwDQs7B zXk}zAH5YvWrZe|9h+P(I>RL-kU8}ROl==QHJ{xoi3OI?>0(|uMXQg}h?_#RZ?9q?v z>g4lvbtU-joOj>2A@&lI4ntjvl(z1H?pX8cy1K{leezXZUDNEkoL( z&~#1pev{?h6rg;Njb?}2 zzpG)oA7%5>Z}plGylLG5)6mwlzW!@t*lmC_0n>s)3^CI9@k}26h3a#Bz8B7%;ZH64 z7klPU2vF{+RinqS>P`Z*V*os*(D7 zMUvcjmL3>s?`zk*X;Y-PunGJ;YySh(C@Cq0Q)|uF8^d_>4J8Cz27U?Ms_w?6zr-ni zIVgxWjCDiUwiIh@(G85m>3@s!n3NzxY;hBMJGm^_A2$)8#Q@SPyDfg?mxn}@4`zgQ zcf>({%NoIv%n^zQaBX$sp1|exA*#NdgH>kZo<&uixGVG*;FG$Gh@e5{xN)1*F62oh zBWzposRd!a$LmMIn4J>oy6$n@?6(QhMAC-9(HQRG=7J5#H%Z9>D?Ezqj-dvItjZ)s z!)EktljOpdr$>O)#y!$Y+Cw)x+$M{3OyIi&AC`GRh-2S)OEdYX4~DWBB!9(yaUpo7 zkFu4yIdj1PRIT!D#_qI|da*vf zk~;14Y;ZE-D8pNwN z$HSaNuD{e>$YDqQr5v@@FKap;C9z-{YmT;nz^a+lLHNa;-c0&KkZGo)eMh`Uf6x;3 zgyzRPf=#kXQ-W5Zk<>prxdM-8ZPIWP=Tvwe?D&qzsKWf&;5N=;Wyr8g{usU=dyA4-bX)D#1>{$L{gQ8FDQO7l1w zHeuCOFxHf)z>wEkN!rxl3AVldMV=wDR7zRhk);oL43m1TuWG53z-%sQ09AOrOIl5< z-ghpk6VO~cM}id_&PQ?!yK&+e%B z6EcVVr(9Ob;jvay>$?7o6$iU0aQV~=nEZV_3w_Vgq?Q|2YVGAr7GT#IqFkM z6*I7^UhE_}gvIXLousD(3lSY`hU`$lN2EyfwnAkJh@VOgWSM<&*qGKu>O%-y+2yVX zd#{V6o_7T^J{Kf+<#U01Xjkc80Ry_Mo7Da;c>cYcw4c{(9xK>{H@(WcV~G3mV$nd6 zl|+DLD}P161+Y|UPrw?WfLczSGM*hj=!E#RDjdg>eIXjQ^^`~o(aV{sxv)&P#8N4cUMnMFJ6Zl%&ngx@$EiH>Q3b@8YDT%-8Kls0QcM=sVnji7%V-= z6H4knA%Cuj*(227EF5uf9xT0W(ug*28SKSn50#|5;A`hl2?jGDS;A$;T3j8GhDiy2 z>*|}xMh}z56Sjv*AHi9XA>9XdTt9TblOatOX1gb4V*YIOZVxcZrSpVZ?B_{=Xdn$B zqHmgC>CaR4K?}F1zvtpd>4>S*nI)LY8i95bivWAkJ>$i~e8F6pUj}i*7?@bf9Vsnt zON=0G|8wv`Fu_-SN}!8(#=@WEK{SCAOYxVoE^cseI$$HE!WC+5yeoA1q@WZfvV}dk0pa2a>K?C#vP zwU{AAfvEbuq47c{xGUtJWGO6+9PpR#Dm8O9xrqjkC#4+$Gd+P zXLj`H!D>=$NqWc_s=LC&H|F|50WU8e!+bV|IY!mK*-|7j{9v}!jW3?wbFkih?#8kq znk)>+k7hX0ih`XKDUoH(lV(z)v-5bVf6kMJ2`~rRj1G6Q6?5UOHF*Ddsff2~OM*!{ z_4ItH8^u2{Uvi=@Kg^fj|G%h@*dCX*6gqx0vpzQ>gW0=}OIiFLE)fuo3!M?s^g4zt zkQ`LltOdNVf(6oGz7r=7ohXQgf;X#tKR&E5BivlHP&ye1O=_-Mt#hJ$xkM-Kh6-xU zXvJK#NP3cwIWMkIP-uG=PhKsO93hmKq*bG-mOt)0E|U7g%3axyF|c2;4=CUDaZ?+c z_JowCF#xH|nj_iRS`q)57fT6L-PVhxcEHWl#nR&qt3IxmE|!9Ec9pK6W4p1AOQcqK z1b6BZ=|znJXvvb7V&!?7WiFLkv8o8@DCI5%Ee3|xFMD7MvZ;jOIlP1wIZ`3N5dRb^ z?8)z8fVR$+dIes-h5a1D8nBUGRKADTmJwK~QGHnQDHXjZZ+p>7ut%uIYb%L5-IrDZ zb>IesRbbt^u=G_@8`!&0`ZK$$zl(|Tu%3=VazdHjoO5whOsSA zOA|TwK$=hbq)k-yISW{gUgz8cPSBjNN>Dl)eX$xdkVZ~bxOq=2>asOpPxxdpmrbn; z7FqdPDG{^8^|e@L0>W?L?hG=dOmo?pby8>F>F}aO!IxEUg;|I0hp;hoxFC4x@GOYq zb2ji<=@eh>7PHLz@g!q%J|^SM?0CKumqhdB0;Kh<>rG@PXnuN8j}n8!+P(*KHl>SU zYShscg>)~F&O_oKxE|Bjb1c3P`g~;fKfr~!BxR-53>i8f+Xip6wnokF(NZO?ny47>Rtm@DZ+d z0j9iZ=1RdwXNr1-USV@K;tD#i(58)s+U_>gmfHr_Q@;A&0{8s4z`b`1M7?<9_jv^V z(cMUd4`U17%EVoVJuzG93js znUv;C1fqz}XqMMm1;QEqQU8=dT~~iBfZ?%#aOTJ}`(u`gFR|NAuZ4S9(YKaq`T`+Z z+5;ZVt2allqx7I5kY%k2^2f9EjcG>pJ!J50WVhM<-vSSN1pX7l^|oT}*77$z&tsqo1eU#S`R`z`Th#BgO1ES}pX~6Z< zThV9Jwn#7=h3mnFO|k}g5((Aw zZQKV?oRR9R!rzO4@pMdRcqTyB2OPCYU*3%A%Nw_oKO2Az6Ou>JQ3L(;$LE7jN6m4M zBx7HYwnPvnXpj><5noV$R4-xCPp-q2|A2?LW_yBq8C z%@@(*?^6)V+m4knztqPpEN7XoA}r0@3;nl4lXvB^%rDVdn|5F?a1zf|OM`h^mg0qG zTz;jh6|l^m(!;_B?C4Ic;#vVUJ0WQJkQWdyVzF=@nRft;gLmbEnkwXGVLNjz>Sm|X)SCl(AxTvREQl$+n1$R;aqwd>*y(7;+%J4 zv?k@U4|ai@KFw-(fi+*w0$!1#v<-gsL5S)4ynB%{N69$Ele7`evAkEMHXKz;Sm1tBoHxd?&&N#{5wnz4da zUTs)fUu>T;+Mxv7^Y|~>Eu~;{Hp5*nYsxzt6jf+@-M=uuKa`VxcAEdwKEeAiSnEew z+rwa@e{qA+@2@hnb5uEO#T(L1+V6k(rnFSZXX&4T=XWf_{g-KPfuXD-*&Qrp)f>mi zI)a^bwHr1ymYaBexi}Yl%^A4-kTD&y>a}l6SrK$*Kx>zXPv7&Ad}JxB{R0;lqsyg< zE$>c}>fuOZ!eZOYrRSh;;Z8j+9a1HnOW4#eK`_~yaCs#A@nG}I(eFqCMorAST&hvh zLUysVA}DiazbjqrsLLtzb%bD|RjQso-~S^H%X<%!iX-gIdxk6>C!}KDeYtF^CDvY8 zx&V*}z~?bFg1eqVv+_;|Ciug*wksXt#k zD=jk>G-qe8Btba89om1TgTd=&{To8{0`|kdLFNT4rUDZr^_4d(Ifk+`DlkD}Z(boS z=iau$%;C7@Pzia*FKk7nB=RmF4NDr3;8#>i75pG!39twY>2HKXh0Yt&!1L#%gB(9g zahQy&EyW)}%#A8t{YW~86$55lup*pCNx3ZWV^!KP^kb$sTYH#v%G+CySwT;>7Xh80j&r={PDXVJ|b(q z%VBi*2Wh#`Vgz^xVo=Dno0>G)j3VeaeE_-mZxH>4t--)Js0}atQ5tL-D6l(+rBHV9 zN6BhY5bVQBGLoV!$u#w{>OikBp%sh2Cb{G&_>dd%XZEFfs%UG_XWeUG3OyI!Z;^s zlavVAihJl!(hYSsng-JxP;Serl_V0nARy9RTr1U>c;`(+A;i2v-qQ@MPw8(cynd!) zCA}jdRBr?8RrwD#gY0cLEY&am5VE^pSj_L3HIKOO|6OV-MDnU=IeG37!Je(YfhFk( zyKqDL5!{;l#2=Wp_?ZYVnPslW4ePXO8QlM0;H8hSqkl=g|A}yS;NKFACNE~kZ%NOC z_$J+!TJagd!lvE^1Hb3CkCBtEp!(qX;4QgYvlly?asw58D%8>v!+^hEYXwEP8{wRcD?y`;7`MkcMXGpci4 zbpm4L{`Kn!ZCt2%YM0H3mG1-HoQahmg_9l!bb*TEkVyes5-0bjoy5Q5ndJa3kFbRfxic46`mzEUhoL7OvW;&~9I_HX zlZzE~knq7!LXp&V60;l^(U40w7zxW3mNyQ{sA;mCNF#2REMMlC4Ry)f zn&dXk{mCVFf*onlOdKm-24mZfB~IJMQka3vN|0%Y^RCZLkcZ&6b{=MB*AnEleC@@( zDku~edBtJr1pA2Vo|-JXEtg%>zlWrwDPl86GR z5cU>}VW*;oc z_~T3@9^cEXwu5Z<{S73UhPvH^3b9}put;>2?GZ=6S1UxFOf{#!mav4A!|v%QhYg&K zU{8!s0jxKaI&z?voRC3(P6Hecm?j_GEV4z04gU*zWgZA^au_fz@#*+$ zR~%@Tc9sYDeu8Az@cqh!6xk)e0Hr!Alo~?~p+Di1hMXTkxF0Jx1x_m~MV2h*po|AQ z@#o^~7U~gPwM>!iEkel`U{ie5OxpdD9g2bYh#ZMECjUp-r4%`ADjfz;N9n=i@LR|5 zpV0Wzvmo7AibECC{T!Mfm9G0aH9t7qFNcllBD)|ATGB=C*>MeWq$cWQuo-sNsIqM} zKgxYA{5<2}(o7dQOs=}n*qbopNpXZoC=LDr?4)&-tpNuBQ>9cTIC^gh=NdD*qAs`% z(^cLt++gY5WV`SO+uKbZ!HTcorrJ&VJwf=B1@@K4u&nO#OxWheWusOwY0Vv2fhGtB zpvk$z9cImvqgh%HEKssSScKe&esWH!u^V`V{q%*P873y+u)2{tEBl7Qr}ZOF)kiInfbH zhyf1OVODYvn5e`WN+=!;1#X zV=W0hP$&TsGx~uYUNBhBu(W8LqOcsI|C@tRiFg=&IAJo8}<~GvDFTnr|>YPM6hFPf?}C%xIEU>1+&BRcF_HBIYsEoggKN; zUJ{hZhs()0{BQ86>V_9khHRi~u_I)wse1%#y+LltGA`he(SHd7B?VTIX_B2IZW zUhk+GA$Jc-HB`N41WO$$$C}bWt|P(Qrbn=SBjrV=UJI+YrAGVA>JTM@{V; z!5$hVcQW-uGv37|(s`A*l~}bDomsUS{CU+VIiX#DEe~3H2wej-n6~`{4>Xi9D1vnz zEw2k2Z15iv!9E`?D;6j9AwOi|^6-0rv@vo!(@?ZHCQe~T7DJ~Z`!VPs=l7M(reP{- zipGK;&uE|<4rdY^$D)&=?Up@ofjO`bZnM^B%y`%gJxpT7lQ9Q8X9}DSbKzi$FcAkm}plWhJlxpQ{*%(+Z@wrNs!7WWXV!swt;Ns;3Y&k zE^@BH`%%C|!Sf>6tX+1+eI!dhE#%CHFD*7SlnEn`8Q{ka@B#z8&;Tzoz)u+9#f{;d zCQBN7G+AnZa}02<0nRhP%M9>x1N>wo7z%?c8hPLWZUg+30bXT*pEkg&4e%NRyw(#Y zg~ew)JpivWz|R`sd;?ryfY%$~LIb?P1J0p7-{|2%aFGFK26&SJ-fV!MGr-Rq;4KYs z4kx;;4IUicW`JKXz{Li*!~kzMz%Lr$9rZBqPc7bA@1epk8Q_-<@Gb-ViUHnjfL}Gh zdvuukpDM6d_t4;d26(>#E;Ybq2KY4te82!7)ZiR_+`n#!aL53=4e((D{DuL3(*VC^ zfRCtfPW{Al)DYpA0e;&6mmA>Y2KZkF_#FfME{B1C9Ru$fBAhV5?;GHg2KWO5{GkCp zWq?l;O#QD{;EW-{Sp)oU16*N%D-G~D1N@NzJ`Xs@bMF7x5aAO8{HX!{%m807z@Ho7 zFAVU-2qpA_(ZBH#0Ur#j!O z4rGC}qx?a2uBy(Ds&h?suB*;Zs`Inz)Tj;=S1CC(L&^D7b$(Nw-&N;^>fqT%igHtR z{#2d6ROfHixurU{Rp*ZC)Ts^xm8+2)CJ4#F9-ACI5=0J+Op#+z9dB}Q=Vu)lqm0F5 zpJ+Dt86PIB$M&gWHaI0~{qJyA(-SeWUktKhQ%y07*1*1X@m585lsgya2!U#C-nKhn2@gdhW>63=F?()PP>Y}D z%Fd8r&7by0G}(p_%qkZK+KaA);V$oatGRWkA#E67eTzeKA>!ppG)f#)cqD7R%MNQe z&%@r{#I1H)(I`#*F(|^24Qx4|cobEL(){%*L=(*BMB(h+HV;*gF{Fz{5%c6wQ(PoF zdm=KH9gc)S#oT!~0&=jtBEsDWbV1f*=))mxa5wMbJUKWd-cX2>7n1o`C|=7!8(WBm zLL|U?8>xNtQTt>S<5}~u2UCpLw~Yp`T{_FxD!5qQ(~yeP9QH8>(l&DllE!OUB=9g| z;!Q0gS+iD=Ff0pFNtG4u*GltCRQ*`RV<-xSZz(@6`)Td*yAAzr#caQUe3H|A&9Gr* z@MvrFXlL|jZ}jM3^yp~x=tLeaR`nD;q_hy5pUzre)Ckz<28>2=#YOj+_$W z*&;g7ASxfJhG(4fRo?~kj6;VU6lWC0fg(?y?B6I4J$&^42p{u5!pHuP@NxCwn1n5$ zj;uVKVvR?ya+AvJcsbOJiu2?I(}YO&VVhc&;M9)6E#ezQFM zW@CNmnG`2@7C1-EeXd7=Fl|URpQjc$U(4t*kBlDI{1$llEmZw*#p29U@`#)#v;h%= z&ZVVbu?B-N;P4U+#&pKvr5a4)ABvx&!L$?*oU6eks3$m2gXt)m;AI+2JRYRkfQa48lE7X-a`Nbd`l;F^hQCueeRQ-Yto#!+}UqxY^aRCMnmuK5x z6BAk>HBZaorqz+`@(*z>Sw%spO<1EQ%~~yI2y5v#nN#4-I@Nhrb@ElGKy}uuPNC{- zP@Rpea*aF;7rc0KraGHcXS3=&r#jE$ii7O3Y(djik#y01#ZmNrODN(!Bd;=TjU?-R zv8*c8i532&&0Mq&JjXU|ow*1tz3%JK$QQJkbRCY8i`9%vRA;;Dyhs%iS@N^8BYuaW z8+IDH;UzZbS$SB_%bGVGvrzBs(%>Wweno>@Xz*?gCY1w<|EdPlDo5}h4c4h?uLkSX zv`>RW)cC!c?AJVWaw^qeot(-vSSP2~G*~C611v8eeRzDlGR6biVBf z__ka5STGI|UEtPo0i?}tHmLw7G>5rkdLxp>et<)W(*=;yK~a9a+$QiX6yeE(AHgf8 zpv9wv-Bv8O+9#N8S&!BESYt*2qRw+x{lugYCnj&>>Ite=t~$rr)I#}`@Gq9M0hIa< zCuTZh86vz(#BVR!h>E_~@bd)!$s8LYf`)i{@iRs zUxb9aY9lD;Lt=<<5q`e|=Hb@iIHKwzp2JL&!XalnhLw6qIuMgpgw^B}#q0^aX5>2< z3e236&#KP9$>Cfv6yJStWVDzeMTJ^%I?>@zpFv%@F;>nQv66c`0g~sxd~oJ8Sj42g z3FjprsgcS@63h0t6;jH>UcvF_4T%5P0K+2WW;rVGQ-e3ui#N-yI$kh%e{O)kFu)fH zW@V!UySrkuJj6@5H3P$&)~ z%H{U%(xdWcK2Vx^`aSf(754}4$%Dg%AKW3A3q-Ad~w$g?12XWo|dnjuy zxTr+4#qBAJc7nO+3VQP=7Jo(VExf|+zk*8qOb~87Ucn}$hJJ^+Yp%$6ZFR4E>s4rW zfezh~HF7^Mq1HY1SNU0i2ooOd+|uvzO}YkLTcSi2?NrR}?l)zBFYNBfgDp54Z7X^! zG1{H~H=TAWp=@$@1_>Tds1h0pn z2Dk6XcoP2i*DIB`1>uIfzyz1au(Qk!xNI`rtZWkga0?b?iiwT9f`>wqk11g39)S|` zLGZ~}PI<$K<8Y8+sgLpv3%`mOz0WKV%`of^(pERF9%jE(L zbf;yuFuU`8l}%o}ye_PAiDGxB1t`U4LcmvnN;@r}x}__wFf9bl4?-T?Gmur!4Iq0G z&{xXdrI=ZI+;+n55TuE^! zM=GU)@V6UuaGwxyOCt~c_~|xa;?C}{JacGR@Q^%6%tBQDA); zCh}aE3CF}C--(cy4{;#sUiVaoQs{+EGD7h(w4_u}FRi;46UrQtVm%})x2)J?RBv{5 zX61=c8=);ppcjn75qGRBqN+9}P39=}lhqrRLEp0BxO0;!ys-RUe|LFn1qayFrFeh3 zH;gx4Y=aK7u#!v` z>p(dfFOXT04vJ)QhOlj&6GGYA4$3ZHDgpm+t*~+x6vfikg`3?IJ1RJLhjB=1d)5GK z|I0foS1<|I`lIlgrY?A-DATZ^=P`1bA5=AyFi>(+f&Yq6pv;v#7wVhT^r8>2>n{Hr zG635>_^%i?`Gmc!q>Iu!;uRWiD4Kf0Ps7bDoLOhH>R>CbY<>^T(&(ne|A@LD2{tksuF6Z zQPWH5?MrV0)BfCvyLB;8uXTh6h|n-O;_31e324s%m_Qtl$FJ<*dF+3h$W^ z4!cYHDv2hj0RS1ed)!~~r!MdtpeU$#+X2dQ(ggsWxGM%I4#5QK-j>=Dwuk9G@$55p zb0>Z}hZ^+9M~WD9wnR0i=T=FFkA9Pi9i6^XO$kN`{RSzQsibX#UF}TGqS(?z^lA2B zB{zWjbPys@^GC7F*Ko#b8=`FB&mUV^+evsbw0wwiSc4nhNv;}acd*mKJ6Q&~Va)2~vpYo|%Cef|KF}|5&$exN?mk zHwd$t322G`Nr9rkvUo57asJrH4a0xQqm>#+WkBFK?Y#lBifLn%wUou#F-oLX7F}X0 z8mmk+;lYQ=W0lrW#;koSG>q*StCYr&<$m;3y;3#xJn=n*uZ8Y8`pV$L>L^*_B0PkK#!R;e;!N$;^<`GYT(or;vMJP~d6o3ZrUK2Vk}La#!Zk%*LC zDZ=d5O{HXaB2yL!kQ)(&vGPrdgBK9Xmb_z+D%z~fgBVG#nT>7QtX$#K3{5eVy*HcF z$}7yh<2j{+fG1cvl53t<)(Sn<46|Rysdd)qINUbgq9n8O+c>|zwndSIG&OGamQdKp zCvoW7a4$R=u~or?-xzG;w<%6?mu^!Qk^9#+WgT4i>KByP1l+;k1@Y(Evr3eFp_l5B zu?INw->w`6fxNd}c@R$0i^}tq!G|v@OF5?pd38%z-Y&g~X?Xe$Wijl%^URP|RpRID zAdJMqI6&fda6c(Kl?{}`*`3PVdRY$b!}OslvdT?~czpRK`?4~f zrxHC=;CCQiF~EfE*rkNm>)Mczmn1~mOh0s&@|CHt)@i5xu@I*f$C`QnI9cUYT-C^W z84OgvhBCQ{m;MbfJNb$-^RC4=XX(YbA)LHRvHqvxm+n@Ung&F%JG+&Yrh(jzWW}#4 z$=bY06BPUGR)oJ+qvOMop>2;69i*>XBnPCnK;1ocj}poip&w*Zmjyx*_;1^z zbg~ShQHIwa&0(g&QL15U>s}?;Gz7q2rC$UsY{|&Sg^yOsj`;3DnkY5RP(-^B>m)WG z+Ga$B_rWbT@IESa>ZwnN0$it1T!C1jG4qYFEX`}dUWm6zcxl{&~ zN55eV@E{&P?)2lz_bQzZVnPL7K0l%Oqb2v8P{!~{TVN%{KDb$M zLa}Oa;C)`;u-?WVH}SG!efio6aN!Hx*H0=w7EWGJWZMvnJ2HK-iHkmq6>Kk?b5`jI zr|hiqDJNl)&(gf)!7FY1xAGOA3V9fd-;Zt9+FP(ST3P|}LuXyCP`2~@o3X&*KDhhT z+GJk8(CjX)#JWonZk$uDlKa(1$~M#ZDE9gHvJ($d!SGh;pUwS?&Om>w{JfIe%#*2| z5XFXm3}#_sl)LC-XA`v%73q7p|lflhgQesV0z{Oosx|*`0+;3h| zhST~M@TD?>^pS{8N}qrZVD6Xbi+fqw2C(AE2f^Yy=KGk7J_R~%eW?@+_wf*SX%*_N z(s<#V4cIYUSFG;fuZW45#;L)b{k4+p1r;Se>2W6F0rfYAh}C`ZJ6a7MROtabI_yl= zdE1J9rEOVz@bURqlmWcQd|0(&!KUDfQjU%-`$6f_ z)mN1$ELFF!D(}#C`S>*j?{#vv@C9K;V_p*ykLR(vUHeIaJb+VLp#W3VLu!-(e54Z5 z<29)-n}-!v!Q4@HCoG)FqoOhFYZQqm@MUubK>5;EiwR-uy)NiR)+$G!IK^@5m|(}) z|2OtHH5;JQR{AiOAUoR-7L(!Yoh#Lu--5=mdd}232s3IK$}sWM0J>mVV38}hIJX3V$1(kIoLvfz@zKcR zYm^4-lPq|m2Vi8kW zNsPgD(n$`8gDXJU*+KMh&F~oW%i(`27A;QMn3yPVgP(X|h4|7zj1=KUh*TmrK~q&b;jt2a{+~HkPtgunB(@ zRxh`Q&^o5)@aY{@)qXEK+RQZ!9DYD^SDdhmB{g@oig?tcXua=g67ggFalHIDe9ZwQ z_NC0|FN6h-G+{370nRq@DHyxB_%~a3+X_X@-)QGakJMK+cUc4bz(}xXx=yTmt&crq z(d(*BrAf$YH9jKEdAL;K6509Yc3aLVydUM6?0^B@WPleK;Bf}HD`4V#Xal6 zFFaC3W#W&0aWc9K^AB{{rhcaR>J2{ym}XWzm$w1aysyKX0TXwn!)pQ4UQvgi08D(H z4nM+{1iD0=GnNFpqT~l|G;VhoV5&EX@bwhuaPik=7hYw*2fA{4Gy^6PSRcCJcf4^9 z*b{q$;pYi=0?e_&%BsBVA+Z2G31um)EBmq9A5Hea+pwwJ)Fbzw+3g^gE9ES_Ju}>4 zfL8;i0z7kl5Pqz7_wQ*TJ!WNm|8b~z0`l#!k(#To}c!Y=(S#BX1i zUdMJgVM9~gG@Xrw{9v%lVaX!X&m3cNXM@G(78HcUddCy*f=hlOuCSy7xGzWf>b-XX z#-a5ZlK)Y_G~kH)Y__q)7Y3)EiZz?AMzUFfme9Z*23yiN4GnSGyPPxR+QE?PcRw{Q zvRk|<0?WhLv|L5rSm=|$6Kq-O@|AFzkCMjW z(;LyvaG@`jm4pJfw~>-YnA0Pw$q@BNb|KUil@#^58kNqv^jtq~d_S+r8-NL`xR&V; zyEIz}R4>a-2Hi{ybNQRv{>YjQ@Wyc>!-bhm@G*zuk{(Oz>z~Z>=lbKY#Et3bN|-A- zB=t~T-9k48-{HEt3;2@XL=9NkTo^=13wH&#IPk+i`!FAVO;H1Vz*4`?WJ|&^Qd1B_ zXdxQ|dIN&s=h?TX*wJv87`Vl7>u)5hMGkF6gZCZ7WxL-D@Y}3Mgv%ut8@y)%riu*m zs7NwHrYdiguHdQnoWIRkg_3X9tWTRP&0U*VkTc1s}rVu2IEAJ+t#tpQ}WfSN&z z)D_$ncC}BkecQM-Rk)Q$Gs_HoG+)ox*257r9kSZzgYDfBmNtzH72aZjQLZq{7JhZF`eIyI%n*c9 zt!brN0&h>`4`frLTy{$Wk6oL9#cFMo%U`~X>v@E(d$puA{>$mgo(DXi9gPC|5~|tI zb9l(DCdw7uv42(L>|+dYt#+X=%OjtItV^^jE`Az1|jeve1wfB&}tg`BUni^ zxRSNeE`Q&}o_=uDxSm}!9_c;dGz0vj;f~>@#;|vj58#0*85Qb6Euz2Y z8pml;Xn>zIz&+T}Sl8PyH@hSb=(^$F9Or5(Sm?;l1WV7>u)w_r+(7xs;j$}#fA&v0 z8vSYG_I&#ZJN9{GWXH|gB}mU{WET9W?VkAEiK6s&q_J`FsL+pWe!Qzc^q7vuyV?i7 z@KIytp*0hnE_?9KbB)V=0x-*(>rV!tv4_iWx}t?Q*dtC?R7mo_)oOcEOa$ACAoJz3 zNR^Qadlf!ad1)h+sxfu=_<`UOPD!%x;m-p~J z1bq*X^|2%O-uIpeE@(;$?z`ZgE2ycN3zn6d3#ggq2BM6a8kVV*3z&AT%)rboHEgwV z!O~w=YEUjMX8-S*xet;0{r>+yAD?&5>~m)3%$YN1&K$cRonHg49e%J*c=0h#pUl(Y zU!Rp{n*y})b)wwHHDt6N;QjEo<-Cq9 zca`7o{~TZs#*P{#QtnysC!#4X3~Q<~9*Ri?Dj4FKEbmH4K;hX!@RX`z;qp8_)DW9e zk}(P5vS6*Qz2zU#xp0S&r`{KxC2C3!X^}otQ+}2qGUJqbwp&^D=yM=uG@@hhBjUFh zF!6sLcnM${^&a?nz(fE%@KV5pd0G`be#;C$LYT*IxjwB4?SHB2HkLdLZzg0kRYGL* z3Pkp0$!QRfDmJjW@+Ce^S}4Jd3K5H{zZzd!oCvot z-`zrKix_KKU|+k6mA60zRn)@7)yT3;15_qy+0% zTPYz@XpxaMGrnu_71>8Ts636h)oqnvn8n@kpwiX63V{!>?7h$)s2oOO#5T%8>$;j0 z8`>ztkmC0?$^v}mAffys&N>&?!v({(iZA?*wFTu7dCKdJprlmAX4E(m7sVBKqYXw~ zHsVXj67|`Xs{9oCk`YvFd^h1Mf?s_|>5r^AzFsy$U%~etz8bevnj^-;?Ubf|n~ikT zVRn{&5|)a#w^LFP{6jnC0zSvuWBbi9{DA}hruBo1Iw~zf zcNnpD8sA+tv3qw!rC{~a>hq%IsYle=InL9wq31}Oi;vEfsd5Iw)EGFysy z3u%a5tdAeHSU0lXSCe&99s?2Jr_&!_U~k4A;K^(q|>4~V3r^u~s_=TL&GOVKbf zy7W{c{oX?XL=D7%n$}Zs(YU13b?Jb9x~CE)Lq)B+w^9fdH5~3h20a{-6=G2PP69E%VeY?N%g#8HOQ|*o#mEfZpX1I>V;(U96(kb*90_u+I1E|7sQR02VC(grErIE{t9+{qgB{M`y}PvEI(pVLOp=&$30lzz#d0H%@P zA<&-!rn-CJ&j3^Rd*IJm@4?Dopzzhf%1hE0dgmd^M?!na&XPZHMzM@_I4|D+O{gzh z{|VH2dJTuPlE#r2OvvN0n%TpZ)O1cvkZBrz^e6gXtSD*R=YRV>z;@hL!iye*rS|9% zN(gUh7>ntJ!?lbNip78nKEmNzMUsZ&)9+&}dhQ5ih%9|6WY2g|UWN5gF40fQQd;D$DE9YTf^PbrMn;Jr5996Czt!$>D-)@Z3kC&Rssvm|5*S0ar1TU!n z+Q%z8jC*58>Iq^-64<6^l#cq0smgxIehGn|mTB2jIocT&TR1)jND4`gC2;a*2I28D^Zr*puqdAPy#5@abDuJC`h)vC1 z_QOJ~N>C5H=PBcq`p1PzGj?{4HJaHLE71RPutkfMcCzeXJBz)8WG@Fhzeq`x5_G@k zu-BJO4%Tk55+s`)Y|vt*i|lR0tLKTw5U-W)Sb{dn7DvHG2sJ8k3VKgPp3F_OA(GJGWWa zv9x?;xE$bM8}pSua-c)Mo)6wrZscHzx9~7^)+*FG$iZf7;&AE-Y&XT-gY`tm$^Z?EjVo^z8KNKqc{Uho$HWHOsjV49GKaHLK zSPhV)9qgUeN~9d)U~>oC!`O+{AoZ~|;mzXUq&XaqFHs`e$k87*(p=Ee*a%NBzKTPS zU84*&$tp5@0f^;lp@U@&TV>4vog8QjSO$w^3HY*)u z7uq~k4P#Y^6hVSP&!HE!%8gnRwG4o`PGZx_!9AqCsw|Y7I9P*p??{$9GQd`t|Ch`ajvAoYFXW~ePd~-RGFwZqmH9iAcsa?z-rAvz<_l6I#+6fM>`{DK+D>H%_cXR_ zB|DXFUUIULK4~v>SL3kDQFnt3Kg*8oR(8>%xMH&AWSieqg!Us8NM3^ianfD|cAEDn zdw71rQ-`N7Uvb;LrHn&Teal;lzsy_znHI~ElJIzKUmnUsQvNpC9?45Sz2k=e7im9cF95Ymu+N2xM5L%;b7C79-ziOaCKq`j-8 z$}KSH-c=4$ptKnJ^Ct~ia+6U34ZDtK81)1D?y9Dbh3gM+blcpj#BP$OTO@>32f zZAj($^@B>HiBk}nEI5a=-wrGLIc#DvYw=E5MOUzA6-ShX|M1K?`Y)cgWB=k=@^79Q z$Ca~GgT#*%XmrBS?gTi|Ali}9#3#1gv+F{AN1jxIco^-V>V!Ri5_B1HUO%a{;cEmt47xG;rqBOa zY2alZgwBIiI4pB)`zIjWg8};rxB@V=s!D%U!mZC?4W>zmJDQgOegG$dLs`sC9PFij zikQP#=@(#Vdi?}9j2^)swvM=0J_U~y?(J~1*54{v08?ESHh^3e7Ze-2@u{K`(Te;` ziH*ocEr>~d!YF670Z#?|2s`~Vlx&mEg4E3ZOi5+iD37FXQN~zy@i!Fvh$w3PFdqwS z8SyGae~w_>;=F*`Zu`zC(@xJ{Q!^elvRBxgyVxw}R-=x^pDWSwLmNv;DuMNLWIXz%s0?S@cmNBjd{W- zZ=jLUbOX*b;3wIRFR?#)B@% z%jnrgR>4MAa}1cqC^dDi0h4Tz;CTj2TTp^?4VaV)3C=TM&vs!xR#&$<2-iCQIs=U0 zGAG6ZOZy5fd{zvG=*w^~;#HS$oAYbbb1|!~#Ak`9HQt9sH{eK#*V^&5V#!=)l#*?f zy4-;2G=OTc!hk)PUunPtjqrQ}_8_o8AP`b9AW*{HPO8OfQHwRA7Db{KjB4S^UTb9F zLE8%k>_OW)1NNZpMFaMrZM^||(6+&VJ!sp=c6W!dMr_6=|7YrLUs+fNub(Mxcj=FC;N z@}Gz62Dxay4ZQ%4kdp2&vhuWarvZCfy32q)EiEx%PfJS;*wfP8Vt~kR8Utky+i)H& z-^=L;t2~dEza@ysKBMybJ*2Q9KcjxWXED|nSHYEa0j|yDnhh6@Z25dD?iOPqlgc!i zf2&gBStSJ?U_V??c0umN=T4b1cYZ-yF?ZnNbLRum|G1h-=`Ft^0wLs49|IwWjRtv! z!Vv@ZAn2$8dk}QYfISF0ZonP{ePqBM1f5`~F9IPad8?&|S(6*61}9&*mdPn7k+KRg zSWk<}ej*0zr(y`4Km_eGBiqRa7C$%OM-BK31Ac^6UjT6r{0^J&FGT?vExjy|z3{@8 zfi|&DH6lpB94$V546RXZzsI2lTuy2CihNd(mP#-l)2l0go|YlL3!1V6y=aGhlB69&Et% z47fjF`dchM5A?y8`o@BAuu1Ip9mS8&U|hbdz5~{vY=O50hH1Gwi{|*5zff0N9oY?X zaXw(-4@$1TpHTz^VLZzQ5iICOB}Hx+!B-#I7Qx2-s3get2)5!!CD!bZ_2691noQ!TMcI-br9l)&xTLmGdgWwJH~KuX4EY#4E}d?=W)5=_h`| zHVLX+JbV99R$(tsL#R~*>-VdY5Zl@)(laz4 zG+@urY!kuO{i<|<@ziWt4VO|yenjta1*jZ-jr%>k5=2dKzlUZBuJQ0T|<{fIYLglL32Xac2Ye%;GKv?3u+~BiJ7|lmv4(_=`cvQg5Pm-PxwUP`e(y zcGfmVKlc=s<@|Cl;U<1r>Mh*GW6+2`Qrs9=Txd#GTh0eh%mKLhqq z!Ttt3h;6FG^cWzpI8c5AP%YwbD@pRh5p2+HrJ4UwBRAS2 zQ6~#g69bkl!Ik1MANNX8(b_a65n^@o^8^;x*$Q z3jE~e<9?#yPvibEa>ucdKT-8b5vR{WR#FATL+?bOT3E7!7&SfTtSpQwIE)0Y7cP9@;$v54%7xK2r>zS)!bZzfhZJ znB9bO@F*G;%{vLt%H36((x$4zT`tyPuipjg=dzP`l_&6GE@)(&ITs}uBa?IPd7@SG zMLxV$3q-3H3NPL&@cPuMMdTIt@E~J%_?%JO=|=4r8*q*RFEL;bU3=buCm7*N4S1{p zFI!Wf!idY7QWUj9lwO=w&myf9?yK2w=W}-r_fjA#h7(5Wzbr|$_!k)GHHW=_U1Kw!B9yabJ1NN|S#q41(wLNwT7o%~QR^p|0l3o@i^47m1 zdVO=PN?@NrmDnOGk@aP~sS(Y_twzQkO1F(|!g#U2W_Xj}fTBV3-=wyc-w+F}v|W!e zs{s-}FeaL&;zwTtk3GCqXQM?pH6al_9a@usma@Ucj^(O?LmM@k%T6i${!5WZ9{-6fr zkq_MuepmzA8>k;y4|_oUas#!iBsF83vT&&>&8BAg96=bdmishz_im#gz09Vn62Ghe z0Lx2Cz-vxBaRan!wU0@+`K!<}I*J4k{{CpeMb)iQ7QI)Xy4VZkEboyRNX+}-wsuvp zY6?AOlu7Sc;2-aQ-uG-%1SHDQA?k3th&eYzT_xkUn^H7-jr+hqu z?Yv|O(lf%&y~2!}{Sm60Kc_{88 z%4ra(CL~NW!v5_N4zUB24$q5>j8ud8!&>xoVIfQ3hGWU%NOcd1LwB}-*@H<@YJ4Oe z!1qN0Dli>C3w{{aJQIlDcSfnrBw9D0#8(u*9hl9?@&oRGH~y28EOs>Mn) zhyG$%@=ZKhl;c(p;YC)U3rsX!sLp7j_M(MvV-t0S^fBJp#Lft&2w)T?QJq0W9(V~| zaW)YYei3eMp)S5n)rDdI4OPhL^`>eEN_f4g+74-&B&p-EN#_}tB&mVWHTW<|eTK@s z{)2|aV?Sh?6Ou80kY;3eV5=-ywHaqP(=uR&!oADaV&?5&_W2l?#gnxVcIF!#DVHn^ z7dKJGX%C+CR9hP{s}JGirQ0~%i9P#7eVn*9Q%g{pY0cF*Du<7+?af6CIgr{y%`rk= zN5qF)sw=tB+>51ejR+`8QHRht8k&O6JuT3eb^{mD&Mw52i0vt=jnW=SQCEc4ARI{d z=qZp)AMcjr$2I0%CaZL>Ad5u!{qshgAHXpUL{UF{duD4V_elS2a`|E>?C@ zCvY5eR;O_PaN(a@0HvKXoz-Fr^o(AZ^6H{)r+S|HQHv~Eg4tB;#9&E##oBr(dg&&ZtAcHJsL;E1Q3%T7zjaTh&s@ZR(g`~dI*&0^J(2N zsjqfZ<7s##UcpMQc2`>%6-%knA)LU{-@x%^Nq05gbDq2edRkT8RbQ&|-R^48|C-*3 zJ=BDjR3LR2RfMD)wJSpYwUJB%le*Wm6op`>hB0*qtbA1+@;4biL2Q3dHU3|k2YF^M(Wb~=YCooi zXo2j?x;S4wzn7XTMf`UXh8LIEX)pgMmi9VP$UbT}=vMJDmDL5OxFvm5I#_tSkNSo& z6be-D05-d?n#&Q`SAE{p0eAUWNw|Lqzm7`iYH6T}Q1J~KO|*gBXCaxn77t5N+c6NX zW{8>6AXAOyOCKWe1;&PNC;aG3qnE~hCg|($tojExL=yoPlh3((sN9*U4*j1Ee1Ij_ zr{&-b?r){`Q_1Qc&!}V+RD#Y<1;w1yPtBm_9O$QxsgpO2I?MJ zgVj{&h`wR4+EA9x>pLD+!)56L4p;l|!a`WVcYXopO62Cps+Gn8Z2NGq zQx{q3LYe`?Rm*)#ImFcl&fs9_=i|T^jX)Rj+EJ5~p5W=cS>UyXwEuV}AQjcz#qHck0J~5!D zsu_q^Iu-nlSYq>DjtMBrQTJ2z59Fx-k)R+4z6k{5G)Ue4$JKnq@BM`OwE0=E7G@SB zn*(6t2iq;_Sv}@Sbtz}Oc0Q#pGBPY3&=7Ki!*Q)y(ghicJx{A+c`vqOn^Mrrz#d=M z+%vEMqjno-sH6ReB_a+?!7se9+&4gvo{1jg3^N2E-#Nlrw^@QE8aGRw%d3KWLq(wh z66|99=pS5|)(e=N3@qgiQ{!3MGpes2ZKfeMdw@8iIF|Vg7&Ne1MbChFdW}i5)d15b z==-qf+n^Kf*=ojrNpN_!`VMpi^X90Znr9$EeU_Jn#ca}CEU}NUXXmPIA-XM}tBwkz zfg+J)zDPkTk;COu1&%wn$L1b=p}n&D6E!~Nmxe6HFC zqJBOWP5L`aRiVFQDD~`F3J&PH7^}qr8pzVm zxEEZtR2^W{qPnv;oks97bC(IKbYPh}l3EqHT#bbhM{Ka)_p3IDBW;v|3kyKVqF1QB zB7dpv4ZP4izqfd?=T~sf`sNC??>*ubz=p2`7C35I!6KOYD?Z*3m0GC^>udfj=A&TP zZ^~D@vDFHA)r#REf(UdI*G763piwhec7a;hsK!zq3igbTBf52!`n@FGVAX|~XE#wt zUuI8Sw+)fcleuL!L6Esl#K#t9tXJS4pe4cd5yRqR(s}I z8hx=&?eKqDVG7QN2eV!;8UyA*R{boL+-xUfppx<;_!7_;@AcT0QLeOWW2qZ3WRUf` z4OmnNyEv%%4n{hvHef))AA~T4zgJyD4gVy{q)2zf=P!dcZUi$mlT^#L(jZv(5+qe9 z0{fU6?sX-|S?&zb4}>Qct8HTb7cYQ%fJu}F*2ng=SPkTQc|@DIWhfYmBz3N|hwwVq z)nauzGy$_Wsr}`MlntS%ghRH}dlC|^3 zt7lLeER($=^**ntqa}?t$DRdW^~>WHsV#WZCF8? zX=N>;1yb^=D(q1uAs3>plp`@Frbu@FRW(5)1)c=Jl&j}T#l7huUZN!a4vH`N@mSrr z2>ueA8IX!Cg6GBMiUioM0!wB_L&aVo{q0bgDGS3Bi~F{!GyLvDH_P)1fV5$oI^e!l zo2o{$k*acpy|+zm{@;Uj>uc&5GLNQD*{=4ZMNU7sLv0}FPFI$GyIvG4I|>UpcXq0+ zCC)0kkZl5{3Kp-75-=??6d`wh=pV$&O4ZfoFM##dY#LQ;(r&c{c=JuW)#h@&NcP2U zwU05JFk;_SlV}W0c~hN8->=^^I21fR&>|3bL6*chSjCfZoQVY^6~=P+pe(#cIZunS z5=kfI!{X*V4HBT2V2`w}-IUCR-XOAghC9YHT1YrSgn|}}G58UFco@65*(bnTfNbNd zAyAk697gQNBb?auns{(i9%g1ICDfAg7?W9~PtL)nF8&tmH{aQ-#{d5sR2j{(oZw#a zBN~hRaACP4q?LHGHUrr%yWnqmkgEJ&tAj8KC*cx_SnsPYi-^>M|E-oVXJf^p;5gdE zCi_IPak?5wZ}r}HN%IB3lq>bPgx_$Myhe#C+JMT&_lyn1D~jiIHBO77rMy6 z`%5}g2QIGzF92M-l|e?h8+j6P=&voVSl5Oh0c?Rk5D->V@S!>eW@fX}x7Clc`yuWy z{8oJR_um6x>tGUo&*HZgzxVL_0Y5KTPH^Kl6u;;2y8+V?H(;)!BP?Fbf<2577}Z#f z-$wl2A&Va{4Kf%uN(SA6B?)%%9W~tF52btXMAg3YJ8SSRrq|hl77N~vNrv5umLL3n zKWg#-6Hy@?6Gz5zjPFqR(`XYnTW7wj&XfHj*&pv>*=P{SBKNB)_i<4)9w<67ci2Vk zr=?`SYWZJV=9l-YbFrAlyr;JHX=n^1P>XTzfpev7?1h=pFl^K{Bt&-{01<^{R(nsd zN@vT|ZA5E0f4sh24dlX-W+<0vFeDHG5FD4h7YhMGIm|PkEmwz#3r?XdyG+6!>qBgR z(Uy@Psz1`V$6@sgX6va1a_Ne{D1`4jGmaRtUOOu|0!dWv5pZ<8ZjJCDJNVG5Xl%zT zjzVNW6%K)Z3Yfn;pTa(I^f7g_z7sjf-aPP}rP~J|64Mt_OyD z>meu9O1|3vaS}Tl)Fp*cc}CsB z*A%KKo_#Fz!^Zk6)z=zYJ8BfmcVp-5`!&hrzET|#gh)z3Kbl@dWWxSEMG3H_ANX2* zUgC&OVA4&S`Lq7gU+cbvH!LQfSmE9w!(cx$E`S&0Yd_=S&58?#{I40}(U69{)slJ`(u)we*EHB^wN zrhL`_}=yLtJo_iHZq6`2V>AN%tx+Mbg5I z62e%Tmln+qNm`QC4VHk2NenCR1>v1d)3$!-#)P<@I z+4jdyOVMUUoInKN>3ImBN@T4QmByK1hnFVyeXuD`fhc`8uZouzn?Tct{_eviV3fh7 z6bAkXpZ4Z8&B2sIcr*xBLI6K&CRQ*FKl(G0;5JJlt9lg!DXqvjq?u=bE(^bzn&GvLU(5 zZ-Z+!CEm#T>8&MLTh=NmoK5i7gn`)*7UQjfM4Dlga#LLu`L}Nu9aa0Ns6W?GEPhg~dzMjUl9d_c& zM?(n0YIhJ`GI$UOD!vI*+r5&|SeqOq`oH$@ZslnsjT0B?&U*^rdjJdr;LD=5wzjT` zc-o@9+h{pfIU0X4_z{yvwOYtFMV;GYD#1 z!R%7&`g|zrbL(r7WP+Nr6eYge44$Y3vpE>SDsNtGn!WOc>HJ=-5kG` z_;tOPceh%3r-f*pjLAey7b_0YxJ2SWh}MDd>Dfr*04-F@f{(r;RBI;JVl_79gVi`2 zuBBPK*Nh}^CAdo-fw5V6#{_%m4y}_vRhTN~8C1w>qeH`eP~H+&Ivm;9He=B%ao~2J z8mamIH`>DMloP3OsbNv1_61dIN|g4Lm$?V3ATG!h#er({1PCz!-IpPCDRVEte$4*7 zIoRBrJEa>iD%OWPt4G%hHun_~mLNg~cji&tOzync1qRX2#$oLC&!+C}eb0@FNQ0}x-WrlGl zugq}no!n3Fl0Ac-5B1O~D7nsx``=9+0R?w)h}J?Dgb&PPQi zHWwx~b$bZg)C3#z*)DC8XLhe5f$ooja5r#ku|~WC4KqDD51d5WHdxcma%*m?=; zejc@&SlJeEOKD9tU+ZItO__7{15IwKku*}ww-Zf`70;g~_lK1DDiZLDH4;`EY)M+Q zb<#gFfL+8SkcOG8pgHsoa;Ar3`n~4HKFA7dyBUM&23E4x8sU4BwJ|U&O#N1r1Ok)P zOiO}-n@jn4eXZb%vF8Y)wD$8!I{YnTO^q}?>eNR28bqIYL z!LUQ zz~Kd!-4-hhu+>%@U#sawshFsg(F1JSW01+EU563ms$wwrz1GPVy*O1{E6Fn>+1)$! zoGd>P4^3qJ3DNqbc3PmIk9gDJ7T)|QZf_I}n~U8bX}!{3OoN~_t=WI$OPgB35r#nC z$L~r56N}Qc*hgofm1(HYZ}@qZ4qEmn)`Ds0RC{TmC8ahaQa7C1=gEuW(t`PnZco?R zn>bdXw`9k1KcTZ0@6k&u?yNbivyEQClM0=+_S9M4U9=SXw(FvCnI@1W2P_=%%&hOIK4Q#qnDx zSd^-62FrqHX<#dcijC~9jpXYUVm&}CnrIbU(H+&A8_D`S0SgWJ;~Q9tdT5TCi1$## z5_=eIQaFn_4bDFGG<4=mdT1t}dB%uCDF=FJ{iIx~^VC|^t=y05W|ZRiFKZZR#p127 z5mnJsbMRAOstZXW=;y(-%1)2QLp4?H;$fuWGs#w%`=T!%7y)yb(M#hBAa{Fd!rV$C ztB#~$eiQfVb9!qFd9f{--Rcvd`}WbIy`((WBvYeT1=y)fP3Xyl^LJvHt)I3{nlA(v z75&5>qECNdeF1y2zou{@33Uv03U&O#dkuZ7zc!jgNMQrCp|!AodJxD>@c=M#e0$fN z4noHb)Dr#;p&JKk2M}${LmVHZ$y|zaYB1QQBg}7zHkdcY&dQ4+bjlr~ZKe{1 zR@K9r`hQX3W7mgj<5L`?YcBqX}o z;4jhGQ`y=&t{(_90njI8`}ct=E*q^atmzvnh=xuV{Al=~Fy|PphX+&ovN2i)-jTvS zeylc^KTJW~Bar~ADpY@ozUMxo?Z*Jo+l|wvaFg%jwP0KwtwZ}O$7{Ksd~pzirEm5G z@Q>)b^Aj|Gas0uD3yaCdoDG}^>baP0IIVSM%O+|AXaw>}f8r%<4{eWWmuh@+-hh}f zdXhGYvnkkTcHoV!$Lz=P+R4?)$Y=?Rn4&%LuLLoiW!f?6aZH9I(J5L55WQ)t_AWJ~ z;2BiJodf$By=H*}EuN+g@%Zkass$GP4#Ae~I1X@9AJ^8?D_=+$&SuZj0(HyN+8(?n zA+jiY4AP&oGxq(1}fEay3-ME8X}&KU*;){WzWQ_IN_B5P^h_D8Ch(a zrv*USpMO@0PrmpR5UEh)Rgr9?YIlmq>Z+FFgtD?6)Td&ewpuPk*d{a1qjI&g#_Y`u zK{IpnG=91K^*pT$rxzJi8CJRyn}6T=+JHKKh07j8Z>>j{t)8!`xHwEg)m3w$5;tG$ z327klZQ2?(ZGnf_lIk2zo_w$kzOz8vM|TF0tS}4dDi&%&3xp04t9D=)lk=>xe!~da zGhoOjb%2Qf0uGb4fKZyDw0$RR)#<-5OF)f4vlD`8z*96qx>=7!AhDDjFHG$SfHwU( zNSwF#_Q6uI2n--?Urnt17F3HW7HJb`0yJ2Ry%)Yyp3}JIB*7lKcM+#FWzmqAA?Oq*`ho>aV8&T@kfYR;11h7@|=axIm& z1_yq9u)^6^U{_DIw6o03=;pK)n&}_(Y;7%?l~jPak-Ng+*u!B|6sz{t6<~BJ7v6R@ zXDm)Sa#m_Nn8O!WYNR!!-(9JNNibu1kNP1eA)UIXoGExnoJ`cy!V6AdIqw{7pCX`N-VQ?S7}}THC{ZqTI^0nknetrwcpK(UbHPI3Jlq@Vr?GOI&Dgq_Sautv%iX3e=BGO? zkbg9O#5~+%m}@f+P`-Q(OS;HO@O*YQtvggr(q4y*1^z#7hiRhx*9EqO^yLj4;89a> zDU>v7N}|kS%gskUCgdC1Ay1A}{nxi^?Tnnx6U;LKY4v2X$zcsB8trpm9-KC(?!+8G z72esYB^b=j=|nu0nKm7-yxiHTk$x8&x=ZW9nVi~#7m*6tVG-tRqaC@!|`cu(ug8{52aS{5+56nj<20c|0# za$i(AmL-#B_x=M~D(=47hrq_=q;KdksrS*aR}9MX99>0e@4$meCuzZYUt7#I+v>5? zFGEi=x=iC5Eifn<#!9;2R4S*;AgbVTEFdQt4WPJNmK^V3m1W|rBcWXTMbwK)BY}|? z2f^DNVdf7sylmD;@9=^4g}1yJN9pv8Thik&ZQ4?S>#*EZawMv7|Ym3&r2W ziq*F+@oK~QGBmRGT3?%>$q1`WbMKK>cK#!hD(ev^w1yHY*5sr%iY_ayIH@HxqGQT` zuz>8?NiB}*e*L8OxR;f*QHlJ-d6l^4PpQB8a3)^6=n*{5l>Z5~ zyjyCmOtw$8G-<02F`kzYD)eRrOK|P7G8wvdxu1b>ArI(jEs|#IjXu|!-&;yZRfkv{ zBK<_Kw&~elXg#HW+o&D*5-Z4S?An)_i+6{y3Z|`x9l_{BAcARUv@^9s$`rgGmiiUA z_J7N6?$;QSuY)||A-+y(_|{8bYo6EIs_#PjR^qFe-l~L@1W)3W&c#@(>>mvYvegv5 z>NallT+}|3w(~K^8N13?A(a~btrm?J!T7wP<9U`l9b>TgTL`;$l5Z5dsz7-l@H^~< zeqo!Oczk>Icc`AUOQbn;NsG3VMqD=oBh=wD+3CyxY{H#j{cV@E) z4@ZJHHmx6sZm%l_Uu9!?qZ}|BTx4tR=uCRkuHz z_M|A7@}K}CLoTyl3!l#4%UUt*-beN}sgc(asihA`I9ishzaqhB_`RO~e( znQt1pYtcVzB?D)Grrz`W3)CKVi-Sg-(5r3FOH`W%WzP;kn@uRh*%a2vt+&?{BdT6p6R>u6Rj229gp zuYo#R7n`tYc5`4LLTHOtTRrP7wgj2@ANcEj&7eMa*opvikbh4oL($UZsn*~>_yYr` zWM~Mn{9*M18=d@3nC+*FL!MX*Sj;b={S(=Pzi4C9D^c%(P=E^f>hHgYeEs*|AD)N8 z6JirKiCht8=}?SP)8C}q_oHF~JNJtgXAgv~Q*8_#XW7Y(143^hH^K@LJNnyy;qSi> z;6;>H%)S?@H#x2ReX$kE{uSDC^==>sR(=jU?)+c1A&rLMMhXoFPr-4}x`N_Fd$8!X z8<Kipqp4)`rC9Qq|AZa`PDJ|4{>JnQV)8(LfY4^Z2xZ)8Rtc$}TSfijnoH#@xu z41Cga-X^Up;M%Qd3z(!W9@NDf+4!;aQP|q0-PBTB(sMVI#uJa4nrirY()j_d-Ig1y z^rjZ9y@5w;Y8SU0Fl9sgB{GOW$tk-iR*mQ_=|P*?xlFAChtU%@h+exUd)Y&`v|zu2 zi?wyevTtb$`hUqSZM?KkufC=I>MOq;$>#QjPH9Gci-q|PwfIW!=%FU(0xmk+Xm*Cd zeCgX}XMZ9D4ZNKbIoW^`FR8P?%V~nX$J@D2#=@Xau{y`eu;auj1wD4ESJih8F-h;S z?l$M2Fl64@?rhK1Ul#>BCsGn-l;9Wae3MEz80<{IWkK31@!fbClR})|NagHYh;t^jlVX#6}gABpCNI?vZ^X^2Wtj}w)kfpCyX;m%+?=@HRUC$YFK@%w;n3UhY-uc;3G zd#Vp96<#-d3|2;SPl6O@ggbvTAI5ZP$fo7_VrlsThH5ijgZ@;R8S6;C!wIg12ba!) zB(w4bJOF9ChP`)IgwrG+#ZlY4HdsTgz@oP>!nxUe3~}+o@>pjph``B+G4@yb>_|LY zZ!EkCEH|;SN#7pjgw{Ss=o7Z$QP|wBpRrCjbX0L!HZHN|rdn=`@=^MKVm|En!jm z?9t9%Vi`0E0e z3++^o3g)a7ikeQg=_PA`e)L7>a4-2A2!Ffy#OmE%a$c#&^KQw_@ax^SI?nnv2cBrkUBH(Xx%ME$G&3vNj@?d|-$i(nxf~*V-|CllJ4aci@AS_5 zou8VeODy!D^H=Gz?)QOn9$oNSe#jYzJ58mB0AA6PKXk&D_Yds!VdqlZ>ltyx`8VC` z8FAeCy?hly^0&;mhTIU+yR46#S8;u(_X+1H>AJq-g!3a=`dOd(F^CR~8l?{me2|?t z`FOKQpEw=3h(os@q-yc`MSNf#>=P%V2gA|rL(JiCz2(Oj1ObBi_ZPHeR%Ss^9}1?$cK92F3bDY zIR?I$zjaQ9q49HqY5L{l_^@!tJMX-#Z6e2?IoiV+%|3ajD@7rW8&drA+7=R>(NF&p#Mx z(cM2eE6q3ov`;eOPF=M#TC!TB#KCL{D@|?!dEX{%NwR)%+F-tG+Aq%b_>}(QWU@~b zOWf)W+uy&UFB`BqzdBz*AIIFl5>`J-n7sy}hS_WE8|Q$8m)&sU%pr=!-gK@){Jl4w zP4U^Z9740Co-m}9z{*dfxZ!Q>zO36HPSCGg&ec|8zlc40fJp~noUHPe(;_!Owr>K> zcNlh_CF`;4wcU0OksBHn%DwH358VZlh4If#s}Q?IZXzPP^!IK%>r1jNii@yV!-e99vmbuPaPei6|G?PrWd(m=Y=jeA%&z_Jbg`;VCXyj-W`=qR?x zuO=9tx9*6+}9P(vJ&Yh9*mO!5@zoBcp+$2hGXG1yWL?ms^HVp%{aF>}w^c;VeTb7$*ELkEF$Y4J2 zZ#uk*WTyjNADfeqU;-=e00cUgLp}ng0?Sh)moHsof^214`$hppL9QHgGOtwW0oX)Y z7UW8ko1wu$u5tF}@FzmNz#zmeSV0#T4iKVTrme$+U0!m_C^j<86)UB%ayMGMJ`B^K z72DL(73GtNG(@giBd;)50vpiW6~cVOVfc4Cx!mMhO|Ic@z#9G@a&g;A53$S?SOaUv zrlq(Pwm;mZvV|@1pRdD(?N=p>@9-)~OAJPCoUfl~8#c_; zwybEETGYk`{p}VmU$!mURVKmy8b!{H0UigjWI_Z?uaQ?7dBOA=xhu*2u*k#~>zXbN zWe>Ssczz-bN6tB4yCKbrMcbm=dh%A|T-{)pnfit0$06|u=GVlfz!DqJk7_K967Fa+ z6|1JYLdak$>jsCg);xh+C0*>0gT%WgL6?i8qAK1sK^n^>;M1Ce&ZZ83gk=(z#|dPQ z=g5{Oh?YMpDy=49D&Xa(w!p%S1eXmq*SNcc+_1Dv{#VF7SrikfV5UqFjjSkxD&$!O zfm7Kv1&zoN73VmE^)*5exApe8aC3`#Fu}(0N@k&_8zW0~1xin{)2gdEtS#dMd7TD4 zJWX!Mg8Ja#V43FfwLXqE5pA5oBk^Vu2s><=s}<}p^PH?!u)tRCbh)6gK?Pf<8Aar=7#FHDUsNa8g+vQPjOj*z{~Eov}o8^z))mmWn=ECi-N#=#v$qT4$S}PgV-tyAy%l zeBmBTZkSf1K3PxhRiaOhCc4}(ugv>;wa9mk$hS!3%S68Gn+>aC~^xQ(ahZ(9k8`lp4)_b z68XO-8vD9v>>CCWo1?MYMNaM($Y}?a01?f_B6l!5Qw)Wi$`-D*cqeUU zOAO{x>OMu@ZM1WR(XcnE;3#Pi?o8veSB$f_MA14G-B;R2Xu5#cIf31t;OCG(Csj~* zXzhx}4qTvsP_w^QGu{(!PM!`3_iWhY#MYYAsI#qIt?`f;M@{O3sCc<>Pbc?5(YUn_ z0+k;S$`tvKQSm2?ihn2u$YC)+jtHC`6%{|mPPakDk5i7Vq>pOVcy?PXf+skIjbtIs zK*sj9MR_Mh*;V8|#iUf=>tj*nq_Hpu2)oJD%iP5AY2nUIMNfSq++=iK`cyQlBGuIi z`!`SD;OzJzOsLN(f1D^k1j_IQ+xrk|^(DLZkgGi`CO2v4ddB<})9_%z0QsiT3_I4e?-UsYl zSL}Vx^>O_P(Kd1AdR1TajP$Dxprfhf4I~|aX0C?*Nf5rojglX2Y8vB5f-9m?H{s_A zgH5S43#ji<7lh9PF)huM!ol)V@D5*Dq{({A6PYCscD>({%1>AJ^ zg?GinE??ZvujO5^8mO|NzC2nz*h8=caHn@|r>9jRYbyLGg9rcJ|=w$hB z6nkelIO{#bUGee_FfiG!FrJYW%B=pl1270&Li7lig?lU-B0w^L=>*6Iu$cfa1Ne*plL44U0Wcdt3j(~OVYLlek0qd<5we;9ivb)W z0MASDXg5Z=Zis0RT$F9p)Q6>KyMlS8;mn0$k>X06%%^3$h8R)xl5E%ZPOvc|mAC?= z`fO8)E7;FBT1ai$qi?*KwG`uf;cg7ChCH~DtyVCx(A1rF5#;|bK><8S3S@b^Q3S4l zq6plWKP0i|=O zQHNR>!S;Y7tD}h6Nkr@{pe_RHDxhuxg27_KK@S1-6i_b#^%hVc0reG7hJZ2!)K5UT zWlp&a5YRvY4HD2`0Syt*!vY#ApkV?UE}#(t8Y!Sr0?HClwtz+pXpDfsoYJ6rgyofj zw0GL+>Libg=5L>w#}ihVr1^zlnjF}PZOo(WyO0fnmAg^#Mosd!dg|&j76=@fVw9g4>v4EBc=y?Gx70@yP;Z7HI?g{~|6i~i^ z3Iw!DK!pNYEl{&YKt%##0$R)FypI;1dDG=6I)GWR%nTL5_&u2WFN!?C9ilWg{eWwG z(eea~^?9QuuTo3mSnKyOUvl>X(=dW`5G`G3gugDr54{i6@d>t_=g026k8K{Gdx2%H z?IP$cQIsyKv`<6~EXO7&Nhi#gW2W}fT@L%Z(f8j1*e{~aE~lFBMyzc$uFpI!a7!Ft zI6T0}VBHRSDs)(sdPD>t70@vO9Tyo#f8dFHLU>H5@i-+s_I!Y%eTkG*dR*Xpc!8gZ z0v8{`_K;K4uY^DN7@{<-KlD_3Y>g}5;{sE{^Y~WeafSSODS?Mw8N8`rI(Up9MQ&>k zd+646?g7?;2UiKGT0p-D=vM*V5YSBl-4f7k0sSVR-v#uCfc_NF9Rd9%Ac!i7T>mYg z2Uy-QK)8l+3}aLlke7f=0)puf3iB2aw0{Y*2*^rM01Y&jbO3y*PYk#B~ks<>a)u8NfkCuvx5m2mv;sg{gvMDQbg@iSZxqs9q048Ff@WzF) zigh?>vX#5=XhBUX--JPkL1crtHmyz$P9q1`KXP!3S~OwF$5F#X0W}p+l7Ny01Szfu z)sBNeb#nvNxY}v>`%FR6RMD13Pzn!XwiKxAl^k^W%B^D9frG9DxpfTt55Bl2$`RA1 zCJUDO0kUpuq))B!Z!iYgdN{*}Vp!x}bTY1G5kd3A6j89Ibc|u+ z4k3Og5u>w+(S<{D*BEw+0&!K+(>&h~QHSnE9eRjFJp~ea38=S#`Ut46fHDM>DYEY; zp#B0HAfSN)8YG~>BHa)HJuIN10vaY_4ksv}Fh2@3a4SU7X}z5|;yLV!H;+J<`mxMi zt^j#t3`;!X8e|?-<7Li*6PS3$93W@&@fyo!4o**jssHogT0X-(5Ng_MkG9&y?5n)pWgf*9nnkJyf1@we~ zrVHpv0b!}7m`@96hR6l?zbMaH0)i=hf@TW{cYp|*E7Hvq5EfR-B~L)}1++jw3kCG7 zfUt~GOk8I`F7jey6f6;eSVt*vDM8S%oaqmpx{t6+vo13x62vp7T;WYt7~o2LiP4S2 zkM=4ICnJyHOOqkrh*Q8`KoaXJ11x0k5xCj_*XS2dxjqWRS=5dnTr2(jXg5THV7~Lw zyWe*0Y77HyzdPJw$K%aPe{lWGDt_?EViO|WAySc^7wNvBN=(o0>RupO*Bbf0z^-+3 zzap*E3%a|9Nm!(>^>8~7%lkV7}TQEIZ z)ywUcH)6K+bOoD2aD2gHI)vi<`#Ya#77gYfJ`hC^g-5#Ip$#@7Z z>jJcOTK93!;IA{!V41NnhH|uzdzsHB)Q$F@qZ+W0?Yx4_FVkrXyU1(-`m(<6*0MPU zCm>!-+8pIFQ~P7s@0spVMzrKBPzKBC=f1*WFIN2`1mnKbp}If2zq<^Ihy?>sc*S|B zdu0u9CqbkHkEhL>QRbuAgW@^+_=VnqkSIMk&^^_>1>TUtk3f>61KnpKP%0mUD8+-^ zCTSbFzvp`+f0j7}1EFlN+XlYn^k8?m^g4?f;tq~@0~t^q|B%G#4(*6MTOP=o5G8a6 zqEJ@?fi<=nX<$I)M8Ug^;NUvJB_g=g2qq;_%A7XllzO)ae$xo16Q$b0dw4LUQNIsC zW#1Bz&YC>z4u&*}3if*&NvY~I)O=XpaKwXT3L%h3ZFtxn1yK}--eaE=bU;AwGryte zYlxjFW;yFU6rY0v`hd+L=#YRuWIG5tETALo96?6~bd328bH|Z*iE{afbtmYAfKIY! zhoOX10{WPJNKl1b+n3=fX@ z%D@Iq-PAf!z7{!rW8^@mhP87zD}v7%!KBVmJNP^gh7f5ch8cuNyvY~YjuGy8m@7?2 zy2scJ*awvgRL#>S5($K2U>O8Sl;d zWVvUVFQIH-mc0u0cmVt|?4MvDXN`8Nd^$-i28I<_@o0B01XD3%++D$kJUYfb zHR5|DrP=6(AMp-X089|(yim%g{DT=k;eq2rymV5I`>Lsr4!NqNOp3fdn?ZEpM11Yo|ZPR4;NLv4^IhpcwYZ6!!u%oxggqiw>OSM^A{bv5={5x0Rxk z_{z@Gr(iV2uxV4>-$NGma1N?g&C(wSJ}PqDW6i&CWK~adyZnL>pI8fO?5}LvG^D#h zADlov6btpzR0oTeA?X?m^k?~ z=ynX#X1F`zGkJ!)C&owm(`M*(%y6qROfp}51}2$(pK*T%eFL~3gWf>z+3u!Z@|_sA zv5hIr{1liFJ#e5)E-?_m3tt7*0(6~kJL{|2!dovWg zbO5lN=@rWsJ?B0pn_}_)xO=0&IaUmGY6BtAJC?0@#Cruh;R`$XC7WSTsbq<}m*iIu z@hIGaZ+({DTEUU$QuhSe8mli_>i$LI9ZjM?!ox21>~eQk?&Ucp-=%-G-2I{?`^2)R zR=N*Euv=c_4%dg|yGtbVR9Y(vH$g)^qZ^hib(OmlG&m-&a<>BgdUch%&`#K5&@}U;KTbr9 z^)7U`V#Un8I+PYk`lE1~nrJ3ZegoE1-Ou0z<=9$xbJ;JJ-CgS*8bq;48$-d5mLHnP z4Px1p7u>OOL;l4n=nGiQZL#|K7u=8IDfU>_??rbr*&m(oqWfi`0o0IX>+ayfvOcC& zha6;%%2&^M#hvTT)q@gQ^6JQ7-S>6(3@d8gMg$ombnPR-paS!W98ugQ`?t-HFb1&thTiaqawzjdYw%Yo( z)^4_Ht8J~Kb*Z&3UF>3Qzu(*>1X26;{XfsgW1N{YXJ*dKoH=vOxij|y%|Y4spaSRH zj^cdHLWj~I!8?Yx2$(J{jFLx8gA{(ma>KzA+8#Ocld@2f<{Iru zKPwM;x!>Wo7v%99aZ`<|o_-osLYEdi2Y-ZxIf{Q%4)kGq5$#gYZ2wDnLOd+^5W{{c zk@SW%ld^LI`k)AX8c8{>8=3j1H0)JxHcu+)>*9xner#p;P$1F2dH7AhkGf>(m2L`W z)`ctzTeo37PH9!c7?V94jT4d`*n>=HKjbC?OM)L=d;MdHk3YLZJ)jMIV4L)yHtE5! z^d-X?P>`%$w+XRxht-q1+rz{St#I74t&zR>pGzZpMnZvl_jIvRFd5$ozo^gx=nga zn{;lQbY3jE8N?2b&UeA7EG);5jy8?c(H@HloF|DO!69rnNdYMKj)G(gW^n+uRZi^q zR#nhq6WXLFwnm=RCUbI|^b{=75H?vd6@oC7jg=H)iH5KfLZ`X#s5GXHOvj20WpU#% zl=TlSYLi(kX2!>8+rUfOq)X}Az{%d5c;^kb2IrFbAat(G)wIqPmb=0VS6Jx^^{#M+ zE39&b23J_^3XQJNBz7fgogL@uu4jYM3&UAievOMJ_n^;glQy?WTiT?pZPK;mqj0tl zj(5-{OYEI+fn#8ZFP`>xVr6gxc%U1uga(rpomlZD<}TcDTb-*qiEEtawn;zGCOxlB zdVZVqf;MSeoAkmv)1~be-3e&7xJ`OVoAiTi(o5TiR?dd&ts&h~&N$Xkb6yirBS!K++Hf^kL)5fEY?w#2;81F_}7iky? zyZ(9?%rbG#J$Dj!v)uRh#5YX56vf8kw9D}*mVQ0R@kbQX#X18l*0rd1r@1f=jYn?k)?L2;m^1sk6ZZ;8LqD&Ev8zP(la#a8hh zE%Da1+gqSg9BlE_{*p5;B!#%Kx45Yae%c)qd-Lm=d8o(}be6Jpl@HnkPt zLlF>g3YShKU~Q`5d<3hSO~czK(d5T%X~1z8N&`;1&;W;AXn^xAG&t%Ej)?)`_Om$H zSO^E&=T7(+&Hxtz`h%w6!EBu5B=(m)MLY@K7v>LBg%T@%dMXEGxNVWIoZbDp6(zC- zc#>Ij5lWo@5LPBRh0U;MRJ7z9S9sbLo^gfEuJ9}r(7}pi_!&fUzjX%ZNj{I|aDmp3 zQ;s}4iMi)(VUYA5iCWI# z)yAl$?`ycZuy7=cA$U1n3}?t?m94Ywxojm$b;)D9ir_)cQUF6!v*KY%aUL6tc0j-_knX4+&*plO zZrfR3$H7S~&ve>@rl<(Zz|XA^gZ*#gz)&!cn+JWTu-!xhaUoF&SgHPbuqpDaa@-%9 z!sg)ZC?8FMxVYr-o62s3lhv`SkS$S8t*!Kq@`?D>*iWo$y@eDHAnV3_nuEfj)tWVDu*BbcdWQxR-- z2A?_uri9H9yBkCDwJz3?(Q0t5s)UUbvlOJEf=v~pctJ-QSdklv%i+ZnSa4M-+gZ#> zq&YpsXtJ~X!cxjQq@k1@A%c};rUY+YxL(Q%6kNu3Met&oNK|tw)@>a-1gSygY$<}xKo)BpK$vpSOpOenma`MPP|l~9Y3Q+W1%6bQbY|yQ zfX^^w6>J)U0~O-Pg;cs~8cIoajvQA)`&P;Ni%n#Z=3*Dli2LDWd2mL1Mq#8UI>r;l zm{Ex0sw`J97s6BzhB269uSlz5LX$5JtA_ zcA|3KndQ>P(|GF+_Yt<2AE@Nc#TShl=CGUah+kF5j)0+ESI1VtF^W{AtJacU4cK?d^^ts#N%M6O)-9x zge=6k|B9nzm>zo7hboA8Y_ugb431K0Q&YVo00|NylHak%HH5)7TEuoE$}QN0|7ca& zExOr`@ct9(q31Q>;dgfMcB`#VxtPsl{=!vw_E*W@Fkv2q)x|%^N*ybfumc%y`f#p_ z99Y~wfn0x(&66;4^6}$rv_v8&e;rDO-8(i;>X^5b#d}x0nBrASZ#V*!a*uS6+}S40hqH!cG_hSO5-w#K|4@ zRTu*aE(l(2?;9lvlan1E`$ofLWO?s!VEL1oGCc1K)<}a%-VU6C71qFx>?9}8u3^_o zB3vU9DR8-E+wQ1w9i~B83n6=?ft7mGA;p=G^>}OD^#-;wgf8Jn0HVVZ4GN

h^jWgU}sr|-wr^~g!qh0+zbV9;^KEgPYH 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 Ix<|_Ue@{ZKP5=M^ diff --git a/ocaml/boot/ocamllex b/ocaml/boot/ocamllex index dd4ef8c3c13980bab829b101c8a714966c5cf015..0fe92796177fcc618a6487f8fdf97923cfd4aa47 100755 GIT binary patch delta 1212 zcmX?cTkOPbv4$4L7N!>F7M3lnf0t?&7{oM*JU--SxkdEkR;OJb7pMhS=9MH?7@T|i zFU9u9o8DeF?kz`R)H$ZBEo0TwYrp^L=7z?Pey-2zJqj~7wl2^PE=kGBOp1>Wt}Hf~ zS9`%^jyQ{1v=!%*u8pz#r#CHQ)euPBJfle7d7%<>U8QB->528zcP(Qz^{J~0XwVc6 z?W!_=_rR$3Webu?sU-$$e;Dp;G(NOwzq#3;BmuJ?WZ6Q47aatC7IgE1H)S-cMc>u&wS#0+;xi>9xyQ6^-{EXJ%I4_r~pKqt?n-zpJAb7{FW{ zP?VWhl3I~$@S(%F=2BT|(N*sgTP}*vzdHTma#nSL8xv%>YmlN)24H* zV0AM2wBDd({{rvFxdQFs_rAUOy}%G=oL^!|W?3rGNP{EIM`FGo@V>uSZQY>>1|Jlr z*R5bR6}VE7yirlWmRIJA{B-RXf(FwMuV7WFk8R7a6HQsaqt>_~_!N7%%K|-^c|NHX znR)33xjPa&ZL*sF%HGe6{2m~Dae)q8L1I;Ty9GIgd%Tjq;Ftu_Uh@EjP3c>a(|BSc>bG*2x*`J2CZKL z9e!+@#dmAju~S%=Faa5`(Ng+?&5_Id~!2QpQ^kHsw&d)8#Nv&`|c+NQ^ zvBRFSy zF6bP*7;N|#;RvVFw6xSBgIC;F#kR;LXdYJ-)R@j@{T^YZQ+|Gq!3kD@N7Gn%FHC#0 z?|sJ^8_(%Jt65b9n%Op-@ovieccM|=yRPSj=JbZutZMGO3mxy->TR2Fd5T8yZuhvq zh@f*UN;fz?*+=P%iEm8e{pQE*NtXz+%(!GsG|D_3YNPz6c=z1LVFm;Cy&!OaxbpVC+D=51V{;#>^OPd_I-t6d&%7nQnf z8pEl%$FD6=2L*Xza*4rzkxRu}D?NGap9faooM;xaKn*C9o1bTpe?xt(0T=IvtNFSc zH-fIi8(%?)OWV%dv88t^>XH{lZgjcGi_fmeeNPwNg;!$%0ELl zZda07YiqrsZKF&1g6WNmScT0D@@}lLS{@nles}(w3EQvcPg`JwY@}mJer{&6LCwvFPWdxck!^*0Op4065km4FCWD delta 1212 zcmY+Ddo@2N+?^M?%-JL9HoCh@A-V6@AH12UYS9!%pf;kIUkd+ zlK)XNvT?)O5a$u=ic`ltJ6Yf`|L=$uiVxg z?bXG3ZZVuR$;_c^P+g3WoHC9PxM`(js}VDEJ{GmuPSjx=cbLXuWY85zuox$+Rr{<~ z3dO;4zA>v8W{VMLY~mgqxmBw#3?sM~UCcjP3_Hb$dCq>LcG8NVv*}fy-q~TDMjA@k z=27Te1}hE-34EGJr1B&CSaa-HkX-_5`~CqfiwEwGjB2z$D=%%y(6{-u`Q>k@-L@RS z;i}~8k2dN7MhsKpixHQs-9n8p^juq%)W|($`q?o-Xy)sFvIen%qJ>avrQ-$Eacr zTcY|Bj~icmX@}w!XAwtd0pdj3B1d8yukn+2pi#}Z1hr5IiuGsV%>mRph2qB-E=NyCL|r%0J{)ryI%XF`JF6-pAD z1u7)g)*yT$TaMcdx%Bbm>>U)4X-Ukj&ZM$vOv={v)h_#FTW)r+;;zJ`WG=hmP*@>A z_UQrcMq$C@&>|BobM)}%V8%mqQL>S X*AqVxH56!fOyoVT8i2WV$f5rLm-`yj diff --git a/ocaml/debugger/loadprinter.ml b/ocaml/debugger/loadprinter.ml index 94fd2a7fbfe..d48f7abf40d 100644 --- a/ocaml/debugger/loadprinter.ml +++ b/ocaml/debugger/loadprinter.ml @@ -112,7 +112,7 @@ let match_printer_type desc typename = raise (Error(Unbound_identifier(Ldot(Lident "Topdirs", typename)))) in Ctype.begin_def(); - let ty_arg = Ctype.newvar Layout.any in + let ty_arg = Ctype.newvar Layout.(value ~why:Debug_printer_argument) in Ctype.unify Env.initial_safe_string (Ctype.newconstr printer_type [ty_arg]) (Ctype.instance desc.val_type); diff --git a/ocaml/lambda/matching.ml b/ocaml/lambda/matching.ml index 04df1ac5f4e..13ef33d0fa3 100644 --- a/ocaml/lambda/matching.ml +++ b/ocaml/lambda/matching.ml @@ -100,7 +100,7 @@ open Printpat module Scoped_location = Debuginfo.Scoped_location type error = - Non_value_layout of Layout.Violation.violation + Non_value_layout of Layout.Violation.t exception Error of Location.t * error @@ -109,8 +109,8 @@ let dbg = false (* CR layouts v2: When we're ready to allow non-values, these can be deleted or changed to check for void. *) let layout_must_be_value loc layout = - match Layout.(sub layout value) with - | Ok () -> () + match Layout.(sub layout (value ~why:V1_safety_check)) with + | Ok _ -> () | Error e -> raise (Error (loc, Non_value_layout e)) (* diff --git a/ocaml/lambda/translcore.ml b/ocaml/lambda/translcore.ml index e4e0be49cdc..87823277582 100644 --- a/ocaml/lambda/translcore.ml +++ b/ocaml/lambda/translcore.ml @@ -31,7 +31,7 @@ type error = Free_super_var | Unreachable_reached | Bad_probe_layout of Ident.t - | Non_value_layout of Layout.Violation.violation + | Non_value_layout of Layout.Violation.t exception Error of Location.t * error @@ -39,14 +39,16 @@ let use_dup_for_constant_mutable_arrays_bigger_than = 4 (* CR layouts v2: When we're ready to allow non-values, these can be deleted or changed to check for void. *) -let sort_must_be_value loc sort = +let sort_must_be_value ~why loc sort = if not Sort.(equate sort value) then - let violation = Layout.(Violation.not_a_sublayout (of_sort sort) value) in + let violation = Layout.(Violation.of_ (Not_a_sublayout + (of_sort ~why sort, + value ~why:V1_safety_check))) in raise (Error (loc, Non_value_layout violation)) let layout_must_be_value loc layout = - match Layout.(sub layout value) with - | Ok () -> () + match Layout.(sub layout (value ~why:V1_safety_check)) with + | Ok _ -> () | Error e -> raise (Error (loc, Non_value_layout e)) (* CR layouts v2: In the places where this is used, we want to allow any (the @@ -61,9 +63,10 @@ let layout_must_be_value loc layout = *) let layout_must_not_be_void loc layout = Layout.default_to_value layout; - match Layout.(sub layout void) with - | Ok () -> - let violation = Layout.(Violation.not_a_sublayout layout value) in + match Layout.(sub layout (void ~why:V1_safety_check)) with + | Ok _ -> + let violation = Layout.(Violation.of_ (Not_a_sublayout + (layout, value ~why:V1_safety_check))) in raise (Error (loc, Non_value_layout violation)) | Error _ -> () @@ -907,8 +910,9 @@ and transl_exp0 ~in_new_scope ~scopes e = with | {val_type; _} -> begin match - Ctype.check_type_layout ~reason:(Fixed_layout Probe) - e.exp_env (Ctype.correct_levels val_type) Layout.value + Ctype.check_type_layout + e.exp_env (Ctype.correct_levels val_type) + (Layout.value ~why:Probe) with | Ok _ -> () | Error _ -> raise (Error (e.exp_loc, Bad_probe_layout id)) @@ -1354,7 +1358,7 @@ and transl_let ~scopes ?(add_regions=false) ?(in_structure=false) :: rem -> (* CR layouts v2: allow non-values. Either remove this or replace with void-specific sanity check. *) - sort_must_be_value expr.exp_loc sort; + sort_must_be_value ~why:Let_binding expr.exp_loc sort; let lam = transl_bound_exp ~scopes ~in_structure pat expr in let lam = Translattribute.add_function_attributes lam vb_loc attr in let lam = if add_regions then maybe_region_exp expr lam else lam in @@ -1374,7 +1378,7 @@ and transl_let ~scopes ?(add_regions=false) ?(in_structure=false) {vb_expr=expr; vb_sort; vb_attributes; vb_loc; vb_pat} id = (* CR layouts v2: allow non-values. Either remove this or replace with void-specific sanity check. *) - sort_must_be_value expr.exp_loc vb_sort; + sort_must_be_value ~why:Let_binding expr.exp_loc vb_sort; let lam = transl_bound_exp ~scopes ~in_structure vb_pat expr in let lam = Translattribute.add_function_attributes lam vb_loc vb_attributes diff --git a/ocaml/lambda/translcore.mli b/ocaml/lambda/translcore.mli index 7d55178841f..d78490bdba6 100644 --- a/ocaml/lambda/translcore.mli +++ b/ocaml/lambda/translcore.mli @@ -50,7 +50,7 @@ type error = Free_super_var | Unreachable_reached | Bad_probe_layout of Ident.t - | Non_value_layout of Layouts.Layout.Violation.violation + | Non_value_layout of Layouts.Layout.Violation.t exception Error of Location.t * error diff --git a/ocaml/lambda/translmod.ml b/ocaml/lambda/translmod.ml index 0de6656ad4c..ccbcfd1a199 100644 --- a/ocaml/lambda/translmod.ml +++ b/ocaml/lambda/translmod.ml @@ -39,7 +39,7 @@ type unsafe_info = type error = Circular_dependency of (Ident.t * unsafe_info) list | Conflicting_inline_attributes -| Non_value_layout of type_expr * Layout.Violation.violation +| Non_value_layout of type_expr * Layout.Violation.t exception Error of Location.t * error @@ -55,9 +55,13 @@ exception Error of Location.t * error When this sanity check is removed, consider whether it must be replaced with some defaulting. *) let sort_must_not_be_void loc ty sort = - let layout = Layout.of_sort sort in - if Layout.is_void layout then - let violation = Layout.(Violation.not_a_sublayout layout value) in + if Sort.is_void_defaulting sort then + let violation = + Layout.(Violation.of_ + (Not_a_sublayout + (Layout.of_sort ~why:V1_safety_check sort, + value ~why:V1_safety_check))) + in raise (Error (loc, Non_value_layout (ty, violation))) let cons_opt x_opt xs = diff --git a/ocaml/lambda/translmod.mli b/ocaml/lambda/translmod.mli index 423b75b9aaa..9322a8027fe 100644 --- a/ocaml/lambda/translmod.mli +++ b/ocaml/lambda/translmod.mli @@ -53,7 +53,7 @@ type unsafe_info = type error = Circular_dependency of (Ident.t * unsafe_info) list | Conflicting_inline_attributes -| Non_value_layout of Types.type_expr * Layouts.Layout.Violation.violation +| Non_value_layout of Types.type_expr * Layouts.Layout.Violation.t exception Error of Location.t * error diff --git a/ocaml/ocamldoc/odoc_sig.ml b/ocaml/ocamldoc/odoc_sig.ml index c087051e252..cf3dc667598 100644 --- a/ocaml/ocamldoc/odoc_sig.ml +++ b/ocaml/ocamldoc/odoc_sig.ml @@ -417,7 +417,7 @@ module Analyser = { Typedtree.ld_id; ld_mutable; ld_type; ld_loc; ld_attributes } = get_field env comments @@ {Types.ld_id; ld_mutable; ld_global = Unrestricted; - ld_layout=Layout.any (* ignored *); + ld_layout=Layout.any ~why:Dummy_layout (* ignored *); ld_type=ld_type.Typedtree.ctyp_type; ld_loc; ld_attributes; ld_uid=Types.Uid.internal_not_actually_unique} in let open Typedtree in diff --git a/ocaml/parsing/builtin_attributes.ml b/ocaml/parsing/builtin_attributes.ml index ee8b13eea49..1721e619928 100644 --- a/ocaml/parsing/builtin_attributes.ml +++ b/ocaml/parsing/builtin_attributes.ml @@ -424,7 +424,8 @@ let explicit_arity attrs = let layout ~legacy_immediate attrs = let layout = List.find_map - (fun a -> match a.attr_name.txt with + (fun a -> + match a.attr_name.txt with | "ocaml.void"|"void" -> Some (a, Void) | "ocaml.value"|"value" -> Some (a, Value) | "ocaml.any"|"any" -> Some (a, Any) @@ -435,21 +436,22 @@ let layout ~legacy_immediate attrs = in match layout with | None -> Ok None - | Some (a, Value) -> - mark_used a.attr_name; - Ok (Some Value) - | Some (a, (Immediate | Immediate64 as l)) -> - mark_used a.attr_name; - if legacy_immediate - || Language_extension.( is_enabled (Layouts Beta) - || is_enabled (Layouts Alpha)) - then Ok (Some l) - else Error (a.attr_loc, l) - | Some (a, (Any | Void as l)) -> - mark_used a.attr_name; - if Language_extension.is_enabled (Layouts Alpha) - then Ok (Some l) - else Error (a.attr_loc, l) + | Some (a, l) -> + mark_used a.attr_name; + let l_loc = Location.mkloc l a.attr_loc in + let check b = + if b + then Ok (Some l_loc) + else Error l_loc + in + match l with + | Value -> check true + | Immediate | Immediate64 -> + check (legacy_immediate + || Language_extension.( is_enabled (Layouts Beta) + || is_enabled (Layouts Alpha))) + | Any | Void -> + check (Language_extension.is_enabled (Layouts Alpha)) (* The "ocaml.boxed (default)" and "ocaml.unboxed (default)" attributes cannot be input by the user, they are added by the diff --git a/ocaml/parsing/builtin_attributes.mli b/ocaml/parsing/builtin_attributes.mli index ddaa4d1404b..dc7743b9526 100644 --- a/ocaml/parsing/builtin_attributes.mli +++ b/ocaml/parsing/builtin_attributes.mli @@ -199,4 +199,5 @@ val tailcall : Parsetree.attributes -> (* CR layouts: we should eventually be able to delete ~legacy_immediate (after we turn on layouts by default). *) val layout : legacy_immediate:bool -> Parsetree.attributes -> - (Asttypes.const_layout option, Location.t * Asttypes.const_layout) result + (Asttypes.const_layout Location.loc option, + Asttypes.const_layout Location.loc) result diff --git a/ocaml/parsing/location.ml b/ocaml/parsing/location.ml index 2c7046f11ad..5d77c90d4e4 100644 --- a/ocaml/parsing/location.ml +++ b/ocaml/parsing/location.ml @@ -82,6 +82,7 @@ type 'a loc = { let mkloc txt loc = { txt ; loc } let mknoloc txt = mkloc txt none +let get_txt { txt } = txt (******************************************************************************) (* Input info *) diff --git a/ocaml/parsing/location.mli b/ocaml/parsing/location.mli index 4e124614fee..5bda0f5361a 100644 --- a/ocaml/parsing/location.mli +++ b/ocaml/parsing/location.mli @@ -90,7 +90,7 @@ type 'a loc = { val mknoloc : 'a -> 'a loc val mkloc : 'a -> t -> 'a loc - +val get_txt : 'a loc -> 'a (** {1 Input info} *) diff --git a/ocaml/testsuite/tests/typing-layouts-missing-cmi/c.ml b/ocaml/testsuite/tests/typing-layouts-missing-cmi/c.ml index e3bb3234dec..789af7cba7d 100644 --- a/ocaml/testsuite/tests/typing-layouts-missing-cmi/c.ml +++ b/ocaml/testsuite/tests/typing-layouts-missing-cmi/c.ml @@ -45,7 +45,10 @@ Line 1, characters 12-19: ^^^^^^^ Error: This type B.b_value = A.a_value should be an instance of type ('a : immediate) - B.b_value has layout value, which is not a sublayout of immediate. + B.b_value has an unknown layout, + which might not be a sublayout of immediate. + No .cmi file found containing A.a_value. + Hint: Adding "a" to your dependencies might help. |}];; (* type err2 = b_void value_arg;; diff --git a/ocaml/testsuite/tests/typing-layouts/basics.ml b/ocaml/testsuite/tests/typing-layouts/basics.ml index 5288cc23ae9..6ff4946e0be 100644 --- a/ocaml/testsuite/tests/typing-layouts/basics.ml +++ b/ocaml/testsuite/tests/typing-layouts/basics.ml @@ -299,3 +299,9 @@ Error: Layout void is used here, but the appropriate layouts extension is not en (* CR layouts: This test moved to [basics_alpha.ml] as it needs a non-value sort. Bring back here when we have one enabled by default. *) + +(**************************************************) +(* Test 31: checking that #poly_var patterns work *) + +(* CR layouts: This test moves to [basics_alpha.ml] as it needs a non-value + sort. Bring back here when we have one enabled by default. *) diff --git a/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml b/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml index fb03dd0616b..ad6be5976ed 100644 --- a/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml +++ b/ocaml/testsuite/tests/typing-layouts/basics_alpha.ml @@ -1443,3 +1443,22 @@ Error: This expression has type t_void but an expression was expected of type ('a : value) t_void has layout void, which is not a sublayout of value. |}] + +(**************************************************) +(* Test 31: checking that #poly_var patterns work *) + +type ('a : void) poly_var = [`A of int * 'a | `B] + +let f #poly_var = "hello" + +[%%expect{| +Line 1, characters 41-43: +1 | type ('a : void) poly_var = [`A of int * 'a | `B] + ^^ +Error: This type ('a : value) should be an instance of type ('a0 : void) + 'a has layout void, which does not overlap with value. +|}] +(* CR layouts bug: this should be accepted (or maybe we should reject + the type definition if we're not allowing `void` things in structures). + This bug is a goof at the top of Typecore.build_or_pat; + there is another CR layouts there. *) diff --git a/ocaml/testsuite/tests/typing-layouts/basics_beta.ml b/ocaml/testsuite/tests/typing-layouts/basics_beta.ml index 5d594a189f3..7dc750ef70d 100644 --- a/ocaml/testsuite/tests/typing-layouts/basics_beta.ml +++ b/ocaml/testsuite/tests/typing-layouts/basics_beta.ml @@ -448,7 +448,7 @@ val f18 : 'a -> 'a = (* Test 22: approx_type catch-all can't be restricted to value *) (* CR layouts: This test moved to [basics_alpha.ml] as it needs a non-value - sort. Bring back here when we have one enabled by default. *) + sort. Bring back here when we have one. *) type t_void [@@void];; [%%expect{| @@ -505,3 +505,9 @@ Error: Layout void is used here, but the appropriate layouts extension is not en (* CR layouts v2: This test moved to [basics_alpha.ml] as it needs a non-value sort. Bring back here when we have one. *) + +(**************************************************) +(* Test 31: checking that #poly_var patterns work *) + +(* CR layouts: This test moves to [basics_alpha.ml] as it needs a non-value + sort. Bring back here when we have one. *) diff --git a/ocaml/testsuite/tests/typing-missing-cmi-2/test.compilers.reference b/ocaml/testsuite/tests/typing-missing-cmi-2/test.compilers.reference index 7e96792bef5..f1ee85e77eb 100644 --- a/ocaml/testsuite/tests/typing-missing-cmi-2/test.compilers.reference +++ b/ocaml/testsuite/tests/typing-missing-cmi-2/test.compilers.reference @@ -3,6 +3,6 @@ File "baz.ml", line 1, characters 8-18: ^^^^^^^^^^ Error: This expression has type 'a Foo.t but an expression was expected of type ('b : '_representable_layout_1) - 'a Foo.t has layout any, which is not representable. + 'a Foo.t has an unknown layout, which might not be representable. No .cmi file found containing Foo.t. Hint: Adding "foo" to your dependencies might help. diff --git a/ocaml/testsuite/tests/typing-missing-cmi-indirections/test.compilers.reference b/ocaml/testsuite/tests/typing-missing-cmi-indirections/test.compilers.reference index ddfa00dab6e..a8cd534433e 100644 --- a/ocaml/testsuite/tests/typing-missing-cmi-indirections/test.compilers.reference +++ b/ocaml/testsuite/tests/typing-missing-cmi-indirections/test.compilers.reference @@ -2,6 +2,6 @@ File "client.ml", line 2, characters 0-19: 2 | and alias = missing ^^^^^^^^^^^^^^^^^^^ Error: - alias has layout any, which is not a sublayout of value. + alias has an unknown layout, which might not be a sublayout of value. No .cmi file found containing Missing.t. Hint: Adding "missing" to your dependencies might help. diff --git a/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference b/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference index 642d7fd8c8a..b75953604d6 100644 --- a/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference +++ b/ocaml/testsuite/tests/typing-missing-cmi/test.compilers.reference @@ -3,6 +3,6 @@ File "main.ml", line 1, characters 8-11: ^^^ Error: This expression has type M.a but an expression was expected of type ('a : value) - M.a has layout any, which is not a sublayout of value. + M.a has an unknown layout, which might not be a sublayout of value. No .cmi file found containing M.a. Hint: Adding "m" to your dependencies might help. diff --git a/ocaml/toplevel/genprintval.ml b/ocaml/toplevel/genprintval.ml index 7962bb535ff..78b152d866f 100644 --- a/ocaml/toplevel/genprintval.ml +++ b/ocaml/toplevel/genprintval.ml @@ -427,7 +427,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct List.mapi (fun i ty_arg -> (ty_arg, - Layout.(equal void cstr_arg_layouts.(i))) + Layout.is_void_defaulting cstr_arg_layouts.(i)) ) ty_args in tree_of_constr_with_args (tree_of_constr env path) @@ -511,7 +511,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct let name = Ident.name ld_id in (* PR#5722: print full module path only for first record field *) - let is_void = Layout.(equal void ld_layout) in + let is_void = Layout.is_void_defaulting ld_layout in let lid = if first then tree_of_label env path (Out_name.create name) else Oide_ident (Out_name.create name) @@ -616,7 +616,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct in let args = instantiate_types env type_params ty_list cstr.cstr_args in let args = List.mapi (fun i arg -> - (arg, Layout.(equal void cstr.cstr_arg_layouts.(i)))) + (arg, Layout.is_void_defaulting cstr.cstr_arg_layouts.(i))) args in tree_of_constr_with_args diff --git a/ocaml/toplevel/topdirs.ml b/ocaml/toplevel/topdirs.ml index 6646b245edf..dce7c05fb9c 100644 --- a/ocaml/toplevel/topdirs.ml +++ b/ocaml/toplevel/topdirs.ml @@ -233,7 +233,7 @@ let printer_type ppf typename = let match_simple_printer_type desc printer_type = Ctype.begin_def(); - let ty_arg = Ctype.newvar Layout.value in + let ty_arg = Ctype.newvar (Layout.value ~why:Debug_printer_argument) in begin try Ctype.unify !toplevel_env (Ctype.newconstr printer_type [ty_arg]) @@ -247,7 +247,10 @@ let match_simple_printer_type desc printer_type = let match_generic_printer_type desc path args printer_type = Ctype.begin_def(); - let args = List.map (fun _ -> Ctype.newvar Layout.value) args in + let args = List.map + (fun _ -> Ctype.newvar + (Layout.value ~why:Debug_printer_argument)) + args in let ty_target = Ctype.newty (Tconstr (path, args, ref Mnil)) in let ty_args = List.map (fun ty_var -> Ctype.newconstr printer_type [ty_var]) args in diff --git a/ocaml/typing/ctype.ml b/ocaml/typing/ctype.ml index bedb5d7abb8..87459be012b 100644 --- a/ocaml/typing/ctype.ml +++ b/ocaml/typing/ctype.ml @@ -1148,9 +1148,10 @@ let rec copy ?partial ?keep_names scope ty = if forget <> generic_level then (* Using layout "any" is ok here: We're forgetting the type because it will be unified with the original later. *) - newty2 ~level:forget (Tvar { name = None; layout = Layout.any }) + newty2 ~level:forget + (Tvar { name = None; layout = Layout.any ~why:Dummy_layout }) else - let t = newstub ~scope:(get_scope ty) Layout.any in + let t = newstub ~scope:(get_scope ty) (Layout.any ~why:Dummy_layout) in For_copy.redirect_desc scope ty (Tsubst (t, None)); let desc' = match desc with @@ -1215,7 +1216,7 @@ let rec copy ?partial ?keep_names scope ty = if not (eq_type more more') then more' (* we've already made a copy *) else - newvar Layout.value + newvar (Layout.value ~why:Row_variable) in let not_reither (_, f) = match row_field_repr f with @@ -1319,7 +1320,7 @@ let instance_constructor ?in_pattern cstr = let layout = match get_desc existential with | Tvar { layout } -> layout - | Tvariant _ -> Layout.value (* Existential row variable *) + | Tvariant _ -> Layout.value ~why:Row_variable (* Existential row variable *) | _ -> assert false in let decl = new_local_type layout in @@ -1440,7 +1441,7 @@ let rec copy_sep ~cleanup_scope ~fixed ~free ~bound ~may_share if is_Tvar ty || may_share && TypeSet.is_empty univars then if get_level ty <> generic_level then ty else (* layout not consulted during copy_sep, so Any is safe *) - let t = newstub ~scope:(get_scope ty) Layout.any in + let t = newstub ~scope:(get_scope ty) (Layout.any ~why:Dummy_layout) in delayed_copy := lazy (Transient_expr.set_stub_desc t (Tlink (copy cleanup_scope ty))) :: !delayed_copy; @@ -1451,7 +1452,7 @@ let rec copy_sep ~cleanup_scope ~fixed ~free ~bound ~may_share if dl <> [] && conflicts univars dl then raise Not_found; t with Not_found -> begin - let t = newstub ~scope:(get_scope ty) Layout.any in + let t = newstub ~scope:(get_scope ty) (Layout.any ~why:Dummy_layout) in let desc = get_desc ty in let visited = match desc with @@ -1576,7 +1577,7 @@ let subst env level priv abbrev oty params args body = if List.length params <> List.length args then raise Cannot_subst; let old_level = !current_level in current_level := level; - let body0 = newvar Layout.any in (* Stub *) + let body0 = newvar (Layout.any ~why:Dummy_layout) in (* Stub *) let undo_abbrev = match oty with | None -> fun () -> () (* No abbreviation added *) @@ -1942,22 +1943,22 @@ let rec estimate_type_layout env ty = try Layout (Env.find_type p env).type_layout with - Not_found -> Layout (missing_cmi_any p) + Not_found -> Layout (any ~why:(Missing_cmi p)) end | Tvariant row -> if tvariant_not_immediate row - then Layout value - else Layout immediate + then Layout (value ~why:Polymorphic_variant) + else Layout (immediate ~why:Immediate_polymorphic_variant) | Tvar { layout } -> TyVar (layout, ty) - | Tarrow _ -> Layout value - | Ttuple _ -> Layout value - | Tobject _ -> Layout value - | Tfield _ -> Layout value - | Tnil -> Layout value + | Tarrow _ -> Layout (value ~why:Arrow) + | Ttuple _ -> Layout (value ~why:Tuple) + | Tobject _ -> Layout (value ~why:Object) + | Tfield _ -> Layout (value ~why:Tfield) + | Tnil -> Layout (value ~why:Tnil) | (Tlink _ | Tsubst _) -> assert false | Tunivar { layout } -> Layout layout | Tpoly (ty, _) -> estimate_type_layout env ty - | Tpackage _ -> Layout value + | Tpackage _ -> Layout (value ~why:First_class_module) (* The ~fixed argument controls what effects this may have on `ty`. If false, @@ -1977,15 +1978,22 @@ let rec estimate_type_layout env ty = loop trying to also expand [s], and then performing layout checking to ensure it's a valid argument to [t]. (We believe there are still loops like this that can occur, though, and may need a more principled solution later). + + Precondition: [layout] is not [any]. This common case is short-circuited + before calling this function. (Though the current implementation is still + correct on [any].) *) -let rec constrain_type_layout ~reason ~fixed env ty layout fuel = +let rec constrain_type_layout ~fixed env ty layout fuel = let constrain_unboxed ty = match estimate_type_layout env ty with | Layout ty_layout -> Layout.sub ty_layout layout | TyVar (ty_layout, ty) -> if fixed then Layout.sub ty_layout layout else - let layout_inter = Layout.intersection ~reason ty_layout layout in + let layout_inter = + Layout.intersection ~reason:Tyvar_refinement_intersection + ty_layout layout + in Result.map (set_var_layout ty) layout_inter in (* This is an optimization to avoid unboxing if we can tell the constraint is @@ -1994,7 +2002,7 @@ let rec constrain_type_layout ~reason ~fixed env ty layout fuel = | Tconstr(p, _args, _abbrev) -> begin let layout_bound = try (Env.find_type p env).type_layout - with Not_found -> Layout.missing_cmi_any p + with Not_found -> Layout.any ~why:(Missing_cmi p) in match Layout.sub layout_bound layout with | Ok () as ok -> ok @@ -2003,37 +2011,36 @@ let rec constrain_type_layout ~reason ~fixed env ty layout fuel = begin match unbox_once env ty with | Not_unboxed ty -> constrain_unboxed ty | Unboxed ty -> - constrain_type_layout ~reason ~fixed env ty layout (fuel - 1) + constrain_type_layout ~fixed env ty layout (fuel - 1) | Missing missing_cmi_for -> - Error (Layout.Violation.add_missing_cmi_for_lhs - ~missing_cmi_for - violation) + Error (Layout.Violation.record_missing_cmi ~missing_cmi_for violation) end end - | Tpoly (ty, _) -> constrain_type_layout ~reason ~fixed env ty layout fuel + | Tpoly (ty, _) -> constrain_type_layout ~fixed env ty layout fuel | _ -> constrain_unboxed ty -let constrain_type_layout ~reason ~fixed env ty layout fuel = - (* An optimization to avoid doing any work if we're checking against any. *) - if Layout.(equal layout any) then Ok () - else constrain_type_layout ~reason ~fixed env ty layout fuel +let constrain_type_layout ~fixed env ty layout fuel = + (* An optimization to avoid doing any work if we're checking against + any. *) + if Layout.is_any layout then Ok () + else constrain_type_layout ~fixed env ty layout fuel -let check_type_layout ~reason env ty layout = - constrain_type_layout ~reason ~fixed:true env ty layout 100 +let check_type_layout env ty layout = + constrain_type_layout ~fixed:true env ty layout 100 -let constrain_type_layout ~reason env ty layout = - constrain_type_layout ~reason ~fixed:false env ty layout 100 +let constrain_type_layout env ty layout = + constrain_type_layout ~fixed:false env ty layout 100 -let check_decl_layout ~reason env decl layout = +let check_decl_layout env decl layout = match Layout.sub decl.type_layout layout with | Ok () as ok -> ok | Error _ as err -> match decl.type_manifest with | None -> err - | Some ty -> check_type_layout ~reason env ty layout + | Some ty -> check_type_layout env ty layout -let constrain_type_layout_exn ~reason env texn ty layout = - match constrain_type_layout ~reason env ty layout with +let constrain_type_layout_exn env texn ty layout = + match constrain_type_layout env ty layout with | Ok _ -> () | Error err -> raise_for texn (Bad_layout (ty,err)) @@ -2043,11 +2050,10 @@ let estimate_type_layout env typ = let type_layout env ty = estimate_type_layout env (get_unboxed_type_approximation env ty) -let type_sort ~reason env ty = +let type_sort ~why env ty = let sort = Sort.new_var () in match - constrain_type_layout ~reason:(Concrete_layout reason) - env ty (Layout.of_sort sort) + constrain_type_layout env ty (Layout.of_sort sort ~why) with | Ok _ -> Ok sort | Error _ as e -> e @@ -2072,16 +2078,16 @@ let rec intersect_type_layout ~reason env ty1 layout2 = Layout.intersection ~reason (estimate_type_layout env ty1) layout2 (* See comment on [layout_unification_mode] *) -let unification_layout_check ~reason env ty layout = +let unification_layout_check env ty layout = match !lmode with - | Perform_checks -> constrain_type_layout_exn ~reason env Unify ty layout + | Perform_checks -> constrain_type_layout_exn env Unify ty layout | Delay_checks r -> r := (ty,layout) :: !r | Skip_checks -> () let is_always_global env ty = let perform_check () = - Result.is_ok (check_type_layout ~reason:Dummy_reason_result_ignored - env ty Layout.immediate64) + Result.is_ok (check_type_layout env ty + (Layout.immediate64 ~why:Local_mode_cross_check)) in if !Clflags.principal || Env.has_local_constraints env then (* We snapshot to keep this pure; see the mode crossing test that mentions @@ -3042,8 +3048,8 @@ let unify_eq t1 t2 = && TypePairs.mem unify_eq_set (order_type_pair t1 t2)) let unify1_var env t1 t2 = - let name, layout = match get_desc t1 with - | Tvar { name; layout } -> name, layout + let layout = match get_desc t1 with + | Tvar { layout } -> layout | _ -> assert false in occur_for Unify env t1 t2; @@ -3056,19 +3062,18 @@ let unify1_var env t1 t2 = with Escape e -> raise_for Unify (Escape e) end; - unification_layout_check ~reason:(Unified_with_tvar name) env t2 layout; + unification_layout_check env t2 layout; link_type t1 t2; true | exception Unify_trace _ when in_pattern_mode () -> false (* Called from unify3 *) -let unify3_var ~var_name env layout1 t1' t2 t2' = +let unify3_var env layout1 t1' t2 t2' = occur_for Unify !env t1' t2; match occur_univar_for Unify !env t2 with | () -> begin - unification_layout_check ~reason:(Unified_with_tvar var_name) !env t2' - layout1; + unification_layout_check !env t2' layout1; link_type t1' t2 end | exception Unify_trace _ when in_pattern_mode () -> @@ -3218,10 +3223,10 @@ and unify3 env t1 t1' t2 t2' = if not (Layout.equal l1 l2) then raise_for Unify (Unequal_var_layouts (t1, l1, t2, l2)); link_type t1' t2' - | (Tvar { name; layout }, _) -> - unify3_var ~var_name:name env layout t1' t2 t2' - | (_, Tvar { name; layout }) -> - unify3_var ~var_name:name env layout t2' t1 t1' + | (Tvar { layout }, _) -> + unify3_var env layout t1' t2 t2' + | (_, Tvar { layout }) -> + unify3_var env layout t2' t1 t1' | (Tfield _, Tfield _) -> (* special case for GADTs *) unify_fields env t1' t2' | _ -> @@ -3408,7 +3413,8 @@ and make_rowvar level use1 rest1 use2 rest2 = | _ -> None in if use1 then rest1 else - if use2 then rest2 else newty2 ~level (Tvar { name; layout = Layout.value }) + if use2 then rest2 + else newty2 ~level (Tvar { name; layout = Layout.value ~why:Row_variable }) and unify_fields env ty1 ty2 = (* Optimization *) let (fields1, rest1) = flatten_fields ty1 @@ -3471,7 +3477,7 @@ and unify_row env row1 row2 = | None, Some _ -> rm2 | None, None -> newty2 ~level:(Int.min (get_level rm1) (get_level rm2)) - (Tvar { name = None; layout = Layout.value }) + (Tvar { name = None; layout = Layout.value ~why:Row_variable }) in let fixed = merge_fixed_explanation fixed1 fixed2 and closed = row1_closed || row2_closed in @@ -3677,15 +3683,14 @@ let unify_var ~from_subst env t1 t2 = match get_desc t1, get_desc t2 with Tvar _, Tconstr _ when deep_occur t1 t2 -> unify (ref env) t1 t2 - | Tvar { name; layout }, _ -> + | Tvar { layout }, _ -> let reset_tracing = check_trace_gadt_instances env in begin try occur_for Unify env t1 t2; update_level_for Unify env (get_level t1) t2; update_scope_for Unify (get_scope t1) t2; if not from_subst then begin - unification_layout_check ~reason:(Unified_with_tvar name) - env t2 layout + unification_layout_check env t2 layout end; link_type t1 t2; reset_trace_gadt_instances reset_tracing; @@ -3750,8 +3755,8 @@ let filter_arrow env t l ~force_tpoly = allow both to be any. Separately, the relevant checks on function arguments should happen when functions are constructed, not their types. *) - let l1 = Layout.of_new_sort_var () in - let l2 = Layout.of_new_sort_var () in + let l1 = Layout.of_new_sort_var ~why:Function_argument in + let l2 = Layout.of_new_sort_var ~why:Function_result in let t1 = if not force_tpoly then begin assert (not (is_optional l)); @@ -3762,7 +3767,8 @@ let filter_arrow env t l ~force_tpoly = newty2 ~level (* CR layouts v5: Change the Layout.value when option can hold non-values. *) - (Tconstr(Predef.path_option,[newvar2 level Layout.value], + (Tconstr(Predef.path_option, + [newvar2 level (Layout.value ~why:Type_argument)], ref Mnil)) else newvar2 level l1 @@ -3787,11 +3793,10 @@ let filter_arrow env t l ~force_tpoly = (Diff { got = t'; expected = t } :: trace)))) in match get_desc t with - Tvar { name; layout } -> + Tvar { layout } -> let t', marg, t1, mret, t2 = function_type (get_level t) in link_type t t'; - constrain_type_layout_exn ~reason:(Unified_with_tvar name) - env Unify t' layout; + constrain_type_layout_exn env Unify t' layout; (marg, t1, mret, t2) | Tarrow((l', marg, mret), t1, t2, _) -> if l = l' || !Clflags.classic && l = Nolabel && not (is_optional l') @@ -3824,15 +3829,15 @@ type filter_method_failure = | Unification_error of unification_error | Not_a_method | Not_an_object of type_expr - | Not_a_value of Layout.Violation.violation + | Not_a_value of Layout.Violation.t exception Filter_method_failed of filter_method_failure (* Used by [filter_method]. *) let rec filter_method_field env name ty = let method_type ~level = - let ty1 = newvar2 level Layout.value in - let ty2 = newvar2 level Layout.value in + let ty1 = newvar2 level (Layout.value ~why:Object_field) in + let ty2 = newvar2 level (Layout.value ~why:Row_variable) in let ty' = newty2 ~level (Tfield (name, field_public, ty1, ty2)) in ty', ty1 in @@ -3865,7 +3870,7 @@ let rec filter_method_field env name ty = (* Unify [ty] and [< name : 'a; .. >]. Return ['a]. *) let filter_method env name ty = let object_type ~level ~scope = - let ty1 = newvar2 level Layout.value in + let ty1 = newvar2 level (Layout.value ~why:Row_variable) in let ty' = newty3 ~level ~scope (Tobject (ty1, ref None)) in let ty_meth = filter_method_field env name ty1 in (ty', ty_meth) @@ -3888,7 +3893,7 @@ let filter_method env name ty = let scope = get_scope ty in let ty', ty_meth = object_type ~level ~scope in begin match - constrain_type_layout ~reason:(Fixed_layout Object) env ty Layout.value + constrain_type_layout env ty (Layout.value ~why:Object) with | Ok _ -> () | Error err -> raise (Filter_method_failed (Not_a_value err)) @@ -3907,8 +3912,8 @@ let rec filter_method_row env name priv ty = match get_desc ty with | Tvar _ -> let level = get_level ty in - let field = newvar2 level Layout.value in - let row = newvar2 level Layout.value in + let field = newvar2 level (Layout.value ~why:Object_field) in + let row = newvar2 level (Layout.value ~why:Row_variable) in let kind, priv = match priv with | Private -> @@ -3944,7 +3949,7 @@ let rec filter_method_row env name priv ty = | Private -> let level = get_level ty in let kind = field_absent in - Mprivate kind, newvar2 level Layout.value, ty + Mprivate kind, newvar2 level (Layout.value ~why:Object_field), ty end | _ -> raise Filter_method_row_failed @@ -3952,7 +3957,7 @@ let rec filter_method_row env name priv ty = (* Operations on class signatures *) let new_class_signature () = - let row = newvar Layout.value in + let row = newvar (Layout.value ~why:Row_variable) in let self = newobj row in { csig_self = self; csig_self_row = row; @@ -4186,7 +4191,8 @@ let generalize_class_signature_spine env sign = in (* But keep levels correct on the type of self *) Meths.iter - (fun _ (_, _, ty) -> unify_var env (newvar Layout.value) ty) + (fun _ (_, _, ty) -> + unify_var env (newvar (Layout.value ~why:Object)) ty) meths; sign.csig_meths <- new_meths @@ -4277,13 +4283,12 @@ let rec moregen inst_nongen variance type_pairs env t1 t2 = try match (get_desc t1, get_desc t2) with - (Tvar { name; layout }, _) when may_instantiate inst_nongen t1 -> + (Tvar { layout }, _) when may_instantiate inst_nongen t1 -> moregen_occur env (get_level t1) t2; update_scope_for Moregen (get_scope t1) t2; occur_for Moregen env t1 t2; link_type t1 t2; - constrain_type_layout_exn ~reason:(Unified_with_tvar name) - env Moregen t2 layout + constrain_type_layout_exn env Moregen t2 layout | (Tconstr (p1, [], _), Tconstr (p2, [], _)) when Path.same p1 p2 -> () | _ -> @@ -4295,12 +4300,11 @@ let rec moregen inst_nongen variance type_pairs env t1 t2 = if not (TypePairs.mem pairs (t1', t2')) then begin TypePairs.add pairs (t1', t2'); match (get_desc t1', get_desc t2') with - (Tvar { name; layout }, _) when may_instantiate inst_nongen t1' -> + (Tvar { layout }, _) when may_instantiate inst_nongen t1' -> moregen_occur env (get_level t1') t2; update_scope_for Moregen (get_scope t1') t2; link_type t1' t2; - constrain_type_layout_exn ~reason:(Unified_with_tvar name) - env Moregen t2 layout + constrain_type_layout_exn env Moregen t2 layout | (Tarrow ((l1,a1,r1), t1, u1, _), Tarrow ((l2,a2,r2), t2, u2, _)) when (l1 = l2 @@ -5266,8 +5270,12 @@ let rec build_subtype env (visited : transient_expr list) as this occurrence might break the occur check. XXX not clear whether this correct anyway... *) if List.exists (deep_occur ty) tl1 then raise Not_found; - set_type_desc ty (Tvar { name = None; layout = Layout.value }); - let t'' = newvar Layout.value in + set_type_desc ty + (Tvar { name = None; + layout = Layout.value + ~why:(Unknown "build subtype 1")}); + let t'' = newvar (Layout.value ~why:(Unknown "build subtype 2")) + in let loops = (get_id ty, t'') :: loops in (* May discard [visited] as level is going down *) let (ty1', c) = @@ -5306,7 +5314,9 @@ let rec build_subtype env (visited : transient_expr list) else build_subtype env visited loops (not posi) level t else if co then build_subtype env visited loops posi level t - else (newvar Layout.value, Changed)) + else (newvar (Layout.value + ~why:(Unknown "build_subtype 3")), + Changed)) decl.type_variance tl in let c = collect tl' in @@ -5343,7 +5353,7 @@ let rec build_subtype env (visited : transient_expr list) let c = collect fields in let row = create_row ~fields:(List.map fst fields) - ~more:(newvar Layout.value) + ~more:(newvar (Layout.value ~why:Row_variable)) ~closed:posi ~fixed:None ~name:(if c > Unchanged then None else row_name row) in @@ -5365,7 +5375,7 @@ let rec build_subtype env (visited : transient_expr list) else (t, Unchanged) | Tnil -> if posi then - let v = newvar Layout.value in + let v = newvar (Layout.value ~why:Tnil) in (v, Changed) else begin warn := true; @@ -5570,7 +5580,8 @@ and subtype_fields env trace ty1 ty2 cstrs = in let cstrs = if miss2 = [] then cstrs else - (trace, rest1, build_fields (get_level ty2) miss2 (newvar Layout.value), + (trace, rest1, build_fields (get_level ty2) miss2 + (newvar (Layout.value ~why:Object_field)), !univar_pairs) :: cstrs in List.fold_left @@ -5680,7 +5691,7 @@ let rec unalias_object ty = | Tunivar _ -> ty | Tconstr _ -> - newvar2 level Layout.value + newvar2 level (Layout.any ~why:Dummy_layout) | _ -> assert false @@ -5868,7 +5879,8 @@ let rec nondep_type_rec ?(expand_private=false) env ids ty = Tvar _ | Tunivar _ -> ty | _ -> try TypeHash.find nondep_hash ty with Not_found -> - let ty' = newgenstub ~scope:(get_scope ty) Layout.any in + let ty' = newgenstub ~scope:(get_scope ty) + (Layout.any ~why:Dummy_layout) in TypeHash.add nondep_hash ty ty'; match match get_desc ty with diff --git a/ocaml/typing/ctype.mli b/ocaml/typing/ctype.mli index 5a5f9759f51..6accc6f72f3 100644 --- a/ocaml/typing/ctype.mli +++ b/ocaml/typing/ctype.mli @@ -303,7 +303,7 @@ type filter_method_failure = | Unification_error of Errortrace.unification_error | Not_a_method | Not_an_object of type_expr - | Not_a_value of Layout.Violation.violation + | Not_a_value of Layout.Violation.t exception Filter_method_failed of filter_method_failure @@ -483,8 +483,8 @@ val type_layout : Env.t -> type_expr -> layout (* Find a type's sort (constraining it to be an arbitrary sort variable, if needed) *) val type_sort : - reason:Layouts.Layout.concrete_layout_reason -> - Env.t -> type_expr -> (sort, Layout.Violation.violation) result + why:Layouts.Layout.concrete_layout_reason -> + Env.t -> type_expr -> (sort, Layout.Violation.t) result (* Layout checking. [constrain_type_layout] will update the layout of type variables to make the check true, if possible. [check_decl_layout] and @@ -493,17 +493,11 @@ val type_sort : (* CR layouts: When we improve errors, it may be convenient to change these to raise on error, like unify. *) val check_decl_layout : - reason:Layouts.Layout.reason - -> Env.t -> type_declaration -> layout - -> (unit, Layout.Violation.violation) result + Env.t -> type_declaration -> layout -> (unit, Layout.Violation.t) result val check_type_layout : - reason:Layouts.Layout.reason - -> Env.t -> type_expr -> layout - -> (unit, Layout.Violation.violation) result + Env.t -> type_expr -> layout -> (unit, Layout.Violation.t) result val constrain_type_layout : - reason:Layouts.Layout.reason - -> Env.t -> type_expr -> layout - -> (unit, Layout.Violation.violation) result + Env.t -> type_expr -> layout -> (unit, Layout.Violation.t) result (* True if a type is always global (i.e., it mode crosses for local). This is true for all immediate and immediate64 types. To make it sound for diff --git a/ocaml/typing/datarepr.ml b/ocaml/typing/datarepr.ml index eba3333dcce..6f349ffa64a 100644 --- a/ocaml/typing/datarepr.ml +++ b/ocaml/typing/datarepr.ml @@ -70,7 +70,7 @@ let constructor_args ~current_unit priv cd_args cd_res path rep = let arg_vars_set = free_vars ~param:true (newgenty (Ttuple tyl)) in let type_params = TypeSet.elements arg_vars_set in let arity = List.length type_params in - let is_void_label lbl = Layout.is_void lbl.ld_layout in + let is_void_label lbl = Layout.is_void_defaulting lbl.ld_layout in let layout = Layout.for_boxed_record ~all_void:(List.for_all is_void_label lbls) in @@ -104,7 +104,7 @@ let constructor_descrs ~current_unit ty_path decl cstrs rep = | Variant_boxed layouts -> layouts | Variant_unboxed -> [| [| decl.type_layout |] |] in - let all_void layouts = Array.for_all Layout.is_void layouts in + let all_void layouts = Array.for_all Layout.is_void_defaulting layouts in let num_consts = ref 0 and num_nonconsts = ref 0 in let cstr_constant = Array.map @@ -197,7 +197,7 @@ let none = let dummy_label = { lbl_name = ""; lbl_res = none; lbl_arg = none; lbl_mut = Immutable; lbl_global = Unrestricted; - lbl_layout = Layout.any; + lbl_layout = Layout.any ~why:Dummy_layout; lbl_num = -1; lbl_pos = -1; lbl_all = [||]; lbl_repres = Record_unboxed; lbl_private = Public; @@ -211,7 +211,7 @@ let label_descrs ty_res lbls repres priv = let rec describe_labels num pos = function [] -> [] | l :: rest -> - let is_void = Layout.is_void l.ld_layout in + let is_void = Layout.is_void_defaulting l.ld_layout in let lbl = { lbl_name = Ident.name l.ld_id; lbl_res = ty_res; diff --git a/ocaml/typing/errortrace.ml b/ocaml/typing/errortrace.ml index 2ecc3591d74..2b52aaf724e 100644 --- a/ocaml/typing/errortrace.ml +++ b/ocaml/typing/errortrace.ml @@ -109,8 +109,8 @@ type ('a, 'variety) elt = (* Could move [Incompatible_fields] into [obj] *) (* Unification & Moregen; included in Equality for simplicity *) | Rec_occur : type_expr * type_expr -> ('a, _) elt - | Bad_layout : type_expr * Layout.Violation.violation -> ('a, _) elt - | Bad_layout_sort : type_expr * Layout.Violation.violation -> ('a, _) elt + | Bad_layout : type_expr * Layout.Violation.t -> ('a, _) elt + | Bad_layout_sort : type_expr * Layout.Violation.t -> ('a, _) elt | Unequal_var_layouts : type_expr * layout * type_expr * layout -> ('a, _) elt diff --git a/ocaml/typing/errortrace.mli b/ocaml/typing/errortrace.mli index d70eacf5d6e..0d9683292d7 100644 --- a/ocaml/typing/errortrace.mli +++ b/ocaml/typing/errortrace.mli @@ -94,8 +94,8 @@ type ('a, 'variety) elt = | Incompatible_fields : { name:string; diff: type_expr diff } -> ('a, _) elt (* Unification & Moregen; included in Equality for simplicity *) | Rec_occur : type_expr * type_expr -> ('a, _) elt - | Bad_layout : type_expr * Layout.Violation.violation -> ('a, _) elt - | Bad_layout_sort : type_expr * Layout.Violation.violation -> ('a, _) elt + | Bad_layout : type_expr * Layout.Violation.t -> ('a, _) elt + | Bad_layout_sort : type_expr * Layout.Violation.t -> ('a, _) elt | Unequal_var_layouts : type_expr * layout * type_expr * layout -> ('a, _) elt diff --git a/ocaml/typing/includecore.ml b/ocaml/typing/includecore.ml index 1b1bdebc62f..f0ac0c44b2d 100644 --- a/ocaml/typing/includecore.ml +++ b/ocaml/typing/includecore.ml @@ -230,7 +230,7 @@ type type_mismatch = | Variant_mismatch of variant_change list | Unboxed_representation of position * attributes | Extensible_representation of position - | Layout of Layout.Violation.violation + | Layout of Layout.Violation.t let report_locality_mismatch first second ppf err = let {order; nonlocal} = err in @@ -1006,10 +1006,7 @@ let type_declarations ?(equality = false) ~loc env ~mark name have a manifest, which we're already checking for equality above. Similarly, [decl1]'s kind may conservatively approximate its layout, but [check_decl_layout] will expand its manifest. *) - (match - Ctype.check_decl_layout ~reason:Dummy_reason_result_ignored - env decl1 decl2.type_layout - with + (match Ctype.check_decl_layout env decl1 decl2.type_layout with | Ok _ -> None | Error v -> Some (Layout v)) | (Type_variant (cstrs1, rep1), Type_variant (cstrs2, rep2)) -> diff --git a/ocaml/typing/includecore.mli b/ocaml/typing/includecore.mli index f727ea587e2..5cc40993103 100644 --- a/ocaml/typing/includecore.mli +++ b/ocaml/typing/includecore.mli @@ -108,7 +108,7 @@ type type_mismatch = | Variant_mismatch of variant_change list | Unboxed_representation of position * attributes | Extensible_representation of position - | Layout of Layout.Violation.violation + | Layout of Layout.Violation.t val value_descriptions: loc:Location.t -> Env.t -> string -> diff --git a/ocaml/typing/layouts.ml b/ocaml/typing/layouts.ml index 08632074b3a..9f927236573 100644 --- a/ocaml/typing/layouts.ml +++ b/ocaml/typing/layouts.ml @@ -12,6 +12,11 @@ (* *) (**************************************************************************) +type sub_result = + | Equal + | Sub + | Not_sub + (* Layouts *) module Sort = struct @@ -40,6 +45,8 @@ module Sort = struct let void = Const Void let value = Const Value + let some_value = Some value + let of_const = function | Void -> void | Value -> value @@ -77,6 +84,8 @@ module Sort = struct end end + let default_to_value t = ignore (get_default_value t) + (***********************) (* equality *) @@ -128,6 +137,29 @@ module Sort = struct | Unequal -> false | Equal_mutated_first | Equal_mutated_second | Equal_no_mutation -> true + let rec is_void_defaulting = function + | Const Void -> true + | Var v -> begin match !v with + (* CR layouts v5: this should probably default to void now *) + | None -> v := some_value; false + | Some s -> is_void_defaulting s + end + | Const Value -> false + + (*** pretty printing ***) + + let string_of_const = function + | Value -> "value" + | Void -> "void" + + let to_string s = match get s with + | Var v -> var_name v + | Const c -> string_of_const c + + let format ppf t = Format.fprintf ppf "%s" (to_string t) + + (*** debug printing **) + module Debug_printers = struct open Format @@ -148,8 +180,23 @@ end type sort = Sort.t module Layout = struct - type fixed_layout_reason = + (*** reasons for layouts **) + + type concrete_layout_reason = + | Match + | Constructor_declaration of int + | Label_declaration of Ident.t + | Unannotated_type_parameter + | Record_projection + | Record_assignment | Let_binding + | Function_argument + | Function_result + | Structure_item_expression + | V1_safety_check + + type value_creation_reason = + | Class_let_binding | Tuple_element | Probe | Package_hack @@ -157,31 +204,82 @@ module Layout = struct | Instance_variable | Object_field | Class_field + | Boxed_record + | Boxed_variant + | Extensible_variant + | Primitive of Ident.t + | Type_argument + | Tuple + | Row_variable + | Polymorphic_variant + | Arrow + | Tfield + | Tnil + | First_class_module + | Separability_check + | Univar + | Polymorphic_variant_field + | Default_type_layout + | Float_record_field + | Existential_type_variable + | Array_element + | Lazy_expression + | Class_argument + | Structure_element + | Debug_printer_argument + | V1_safety_check + | Unknown of string + + type immediate_creation_reason = + | Empty_record + | Enumeration + | Primitive of Ident.t + | Immediate_polymorphic_variant + | Gc_ignorable_check + | Value_kind + + type immediate64_creation_reason = + | Local_mode_cross_check + | Gc_ignorable_check + | Separability_check + + type void_creation_reason = + | V1_safety_check - type concrete_layout_reason = - | Match - | Constructor_declaration of int - | Label_declaration of Ident.t - | Function_argument - | Function_result + type any_creation_reason = + | Missing_cmi of Path.t + | Wildcard + | Unification_var + | Initial_typedecl_env + | Dummy_layout + | Type_expression_call - type annotation_location = + type annotation_context = | Type_declaration of Path.t | Type_parameter of Path.t * string - | With_constraint of Location.t - | Newtype_declaration of string Location.loc - - type reason = - | Fixed_layout of fixed_layout_reason - | Concrete_layout of concrete_layout_reason - | Annotated of annotation_location + | With_constraint of string + | Newtype_declaration of string + + type creation_reason = + | Annotated of annotation_context * Location.t + | Value_creation of value_creation_reason + | Immediate_creation of immediate_creation_reason + | Immediate64_creation of immediate64_creation_reason + | Void_creation of void_creation_reason + | Any_creation of any_creation_reason + | Concrete_creation of concrete_layout_reason + | Imported + + type interact_reason = | Gadt_equation of Path.t - | Unified_with_tvar of string option - | V1_safety_check - | Dummy_reason_result_ignored + | Tyvar_refinement_intersection + (* CR layouts: this needs to carry a type_expr, but that's loopy *) + | Sublayout + + (*** actual layout types ***) type internal = - | Any of { missing_cmi_for : Path.t option } + | Any | Sort of sort | Immediate64 (** We know for sure that values of types of this layout are always immediate @@ -189,25 +287,48 @@ module Layout = struct *) | Immediate + (* A history of conditions placed on a layout. + + INVARIANT: at most one sort variable appears in this history. + This is a natural consequence of producing this history by comparing + layouts. + *) + type history = + | Interact of { reason : interact_reason + ; lhs_layout : internal + ; lhs_history : history + ; rhs_layout : internal + ; rhs_history : history + } + | Creation of creation_reason + type t = { layout : internal - ; history : reason list (* events listed in reverse chronological order *) - } - - let fresh_layout layout = { layout; history = [] } + ; history : history } - let add_reason reason t = { t with history = reason :: t.history } + let fresh_layout layout ~why = { layout; history = Creation why } (******************************) (* constants *) - let any' missing_cmi_for = fresh_layout (Any { missing_cmi_for }) - let any = any' None - let missing_cmi_any type_ = any' (Some type_) - let void = fresh_layout (Sort Sort.void) - let value = fresh_layout (Sort Sort.value) - let immediate64 = fresh_layout Immediate64 - let immediate = fresh_layout Immediate + let any_dummy_layout = + { layout = Any; history = Creation (Any_creation Dummy_layout) } + let value_v1_safety_check = + { layout = Sort Sort.value; + history = Creation (Value_creation V1_safety_check) } + + let any ~why = match why with + | Dummy_layout -> any_dummy_layout (* share this one common case *) + | _ -> fresh_layout Any ~why:(Any_creation why) + let void ~why = + fresh_layout (Sort Sort.void) ~why:(Void_creation why) + let value ~(why : value_creation_reason) = match why with + | V1_safety_check -> value_v1_safety_check + | _ -> fresh_layout (Sort Sort.value) ~why:(Value_creation why) + let immediate64 ~why = + fresh_layout Immediate64 ~why:(Immediate64_creation why) + let immediate ~why = + fresh_layout Immediate ~why:(Immediate_creation why) type const = Asttypes.const_layout = | Any @@ -231,25 +352,35 @@ module Layout = struct | Value, Value -> true | (Any | Immediate64 | Immediate | Void | Value), _ -> false - (******************************) + let sub_const (c1 : const) (c2 : const) = match c1, c2 with + | Any, Any -> Equal + | _, Any -> Sub + | c1, c2 when equal_const c1 c2 -> Equal + | (Immediate | Immediate64), Value -> Sub + | Immediate, Immediate64 -> Sub + | (Any | Void | Value | Immediate64 | Immediate), _ -> Not_sub + + (******************************) (* construction *) - let of_new_sort_var () = fresh_layout (Sort (Sort.new_var ())) + let of_new_sort_var ~why = + fresh_layout (Sort (Sort.new_var ())) ~why:(Concrete_creation why) - let of_sort s = fresh_layout (Sort s) + let of_sort ~why s = + fresh_layout (Sort s) ~why:(Concrete_creation why) - let of_const : const -> t = function - | Any -> any - | Immediate -> immediate - | Immediate64 -> immediate64 - | Value -> value - | Void -> void + let of_const ~why : const -> t = function + | Any -> fresh_layout Any ~why + | Immediate -> fresh_layout Immediate ~why + | Immediate64 -> fresh_layout Immediate64 ~why + | Value -> fresh_layout (Sort Sort.value) ~why + | Void -> fresh_layout (Sort Sort.void) ~why let of_attributes ~legacy_immediate ~reason attrs = - Result.map (Option.map (add_reason (Annotated reason))) @@ match Builtin_attributes.layout ~legacy_immediate attrs with | Ok None as a -> a - | Ok (Some l) -> Ok (Some (of_const l)) + | Ok (Some l) -> Ok (Some (of_const ~why:(Annotated (reason, l.loc)) + l.txt)) | Error _ as e -> e let of_attributes_default ~legacy_immediate ~reason ~default attrs = @@ -259,7 +390,10 @@ module Layout = struct | Error _ as e -> e let for_boxed_record ~all_void = - if all_void then immediate else value + if all_void then immediate ~why:Empty_record else value ~why:Boxed_record + + let for_boxed_variant ~all_voids = + if all_voids then immediate ~why:Enumeration else value ~why:Boxed_variant (******************************) (* elimination and defaulting *) @@ -268,12 +402,21 @@ module Layout = struct | Const of const | Var of Sort.var - let of_desc = function - | Const c -> of_const c - | Var v -> of_sort (Sort.of_var v) - - let get (t : t) : desc = match t.layout with - | Any _ -> Const Any + let format_desc ppf = let open Format in function + | Const c -> fprintf ppf "%s" (string_of_const c) + | Var v -> fprintf ppf "%s" (Sort.var_name v) + + (* considers sort variables < Any, but otherwise just checks for equality. + Never does mutation. + Pre-condition: no filled-in sort variables. *) + let sub_desc d1 d2 = match d1, d2 with + | Const c1, Const c2 -> sub_const c1 c2 + | Var _, Const Any -> Sub + | Var v1, Var v2 -> if v1 == v2 then Equal else Not_sub + | Const _, Var _ | Var _, Const _ -> Not_sub + + let get_internal (lay : internal) : desc = match lay with + | Any -> Const Any | Immediate -> Const Immediate | Immediate64 -> Const Immediate64 | Sort s -> begin match Sort.get s with @@ -285,7 +428,7 @@ module Layout = struct end let get_default_value (t : t) : const = match t.layout with - | Any _ -> Any + | Any -> Any | Immediate -> Immediate | Immediate64 -> Immediate64 | Sort s -> begin match Sort.get_default_value s with @@ -296,7 +439,7 @@ module Layout = struct let default_to_value t = ignore (get_default_value t) - let is_void t = Void = get_default_value t + let get t = get_internal t.layout (* CR layouts: this function is suspect; it seems likely to reisenberg that refactoring could get rid of it *) @@ -314,38 +457,77 @@ module Layout = struct | Const c -> string_of_const c | Var v -> Sort.var_name v - module Formatting : sig - open Format - val format : formatter -> t -> unit - val format_history : - pp_name:(formatter -> 'a -> unit) -> name:'a -> - formatter -> t -> unit + let format ppf t = Format.fprintf ppf "%s" (to_string t) + + (***********************************) + (* layout histories *) + + let printtyp_path = ref (fun _ _ -> assert false) + let set_printtyp_path f = printtyp_path := f + + module Report_missing_cmi : sig + (* used both in format_history and in Violation.report_general *) + val report_missing_cmi : Format.formatter -> Path.t option -> unit end = struct open Format - let format ppf t = fprintf ppf "%s" (to_string t) + (* CR layouts: Remove this horrible (but useful) heuristic once we have + transitive dependencies in jenga. *) + let missing_cmi_hint ppf type_path = + let root_module_name p = p |> Path.head |> Ident.name in + let delete_trailing_double_underscore s = + if Misc.Stdlib.String.ends_with ~suffix:"__" s + then String.sub s 0 (String.length s - 2) + else s + in + (* A heuristic for guessing at a plausible library name for an identifier + with a missing .cmi file; definitely less likely to be right outside of + Jane Street. *) + let guess_library_name : Path.t -> string option = function + | Pdot _ as p -> Some begin + match root_module_name p with + | "Location" | "Longident" -> "ocamlcommon" + | mn -> mn + |> String.lowercase_ascii + |> delete_trailing_double_underscore + end + | Pident _ | Papply _ -> + None + in + Option.iter + (fprintf ppf "@,Hint: Adding \"%s\" to your dependencies might help.") + (guess_library_name type_path) + + let report_missing_cmi ppf = function + | Some p -> + fprintf ppf "@,No .cmi file found containing %a." !printtyp_path p; + missing_cmi_hint ppf p + | None -> () + end - let fixed_layout_reason_layout = function - | Let_binding - | Tuple_element - | Probe - | Package_hack - | Object - | Instance_variable - | Object_field - | Class_field - -> value + include Report_missing_cmi - let format_fixed_layout_reason ppf = - function - | Let_binding -> fprintf ppf "let-bound" - | Tuple_element -> fprintf ppf "a tuple element" - | Probe -> fprintf ppf "a probe" - | Package_hack -> fprintf ppf "used as a value in a first-class module" - | Object -> fprintf ppf "an object" - | Instance_variable -> fprintf ppf "an instance variable" - | Object_field -> fprintf ppf "an object field" - | Class_field -> fprintf ppf "an class field" + (* CR layouts: should this be configurable? In the meantime, you + may want to change these to experiment / debug. *) + + (* should we print histories at all? *) + let display_histories = false + + (* should we print histories in a way users can understand? + The alternative is to print out all the data, which may be useful + during debugging. *) + let flattened_histories = true + + (* This module is just to keep all the helper functions more locally + scoped. *) + module Format_history : sig + val format_history : + intro:(Format.formatter -> unit) -> Format.formatter -> t -> unit + end = struct + (* CR layouts: all the output in this section is subject to change; + actually look closely at error messages once this is activated *) + + open Format let format_concrete_layout_reason ppf : concrete_layout_reason -> unit = function @@ -356,67 +538,253 @@ module Layout = struct | Label_declaration lbl -> fprintf ppf "used in the declaration of the record field \"%a\"" Ident.print lbl - | Function_argument -> fprintf ppf "a function argument" - | Function_result -> fprintf ppf "a function result" + | Unannotated_type_parameter -> + fprintf ppf "appears as an unannotated type parameter" + | Record_projection -> + fprintf ppf "used as the record in a projection" + | Record_assignment -> + fprintf ppf "used as the record in an assignment" + | Let_binding -> + fprintf ppf "bound by a `let`" + | Function_argument -> + fprintf ppf "used as a function argument" + | Function_result -> + fprintf ppf "used as a function result" + | Structure_item_expression -> + fprintf ppf "used in an expression in a structure" + | V1_safety_check -> + fprintf ppf "part of the v1 safety check" - let format_annotation_location ppf : annotation_location -> unit = function + let format_annotation_context ppf : annotation_context -> unit = function | Type_declaration p -> fprintf ppf "the declaration of the type %a" - Path.print p - | Type_parameter (p, var) -> - fprintf ppf "%s@ in the declaration of the type %a" + !printtyp_path p + | Type_parameter (path, var) -> + fprintf ppf "@[%s@ in the declaration of the type@ %a@]" var - Path.print p - | With_constraint loc -> - fprintf ppf "the `with` constraint at %a" - Location.print_loc loc - | Newtype_declaration {loc; txt} -> - fprintf ppf "the abstract type declaration for %s at %a" - txt Location.print_loc loc - - let format_reason ppf : reason -> unit = function - | Fixed_layout flr -> - fprintf ppf "to@ %a because it was@ %a" - format (fixed_layout_reason_layout flr) - format_fixed_layout_reason flr - | Concrete_layout clr -> - fprintf ppf "to be concrete@ because it was %a" - format_concrete_layout_reason clr - | Annotated aloc -> - fprintf ppf "by the annotation@ on %a" - format_annotation_location aloc - | Gadt_equation p -> - fprintf ppf "by a GADT match@ on the constructor %a" - Path.print p - | Unified_with_tvar tv -> begin - fprintf ppf "during unification@ with "; - match tv with - | None -> fprintf ppf "a type variable" - | Some tv -> fprintf ppf "'%s" tv - end + !printtyp_path path + | With_constraint s -> + fprintf ppf "the `with` constraint for %s" s + | Newtype_declaration name -> + fprintf ppf "the abstract type declaration for %s" + name + + let format_any_creation_reason ppf : any_creation_reason -> unit = function + | Missing_cmi p -> + fprintf ppf "a missing .cmi file for %a" !printtyp_path p + | Wildcard -> + fprintf ppf "a _ in a type" + | Unification_var -> + fprintf ppf "a fresh unification variable" + | Initial_typedecl_env -> + fprintf ppf "a dummy layout used in checking mutually recursive datatypes" + | Dummy_layout -> + fprintf ppf "@[a dummy layout that should have been overwritten;@ \ + Please notify the Jane Street compilers group if you see this output." + (* CR layouts: Improve output or remove this constructor ^^ *) + | Type_expression_call -> + fprintf ppf "a call to [type_expression] via the ocaml API" + + let format_immediate_creation_reason ppf : immediate_creation_reason -> _ = + function + | Empty_record -> + fprintf ppf "a record containing all void elements" + | Enumeration -> + fprintf ppf "an enumeration variant (all constructors are constant)" + | Primitive id -> + fprintf ppf "it equals the primitive immediate type %s" (Ident.name id) + | Immediate_polymorphic_variant -> + fprintf ppf "an immediate polymorphic variant" + | Gc_ignorable_check -> + fprintf ppf "the check to see whether a value can be ignored by GC" + | Value_kind -> + fprintf ppf + "the check to see whether a polymorphic variant is immediate" + + let format_immediate64_creation_reason ppf = function + | Local_mode_cross_check -> + fprintf ppf "the check for whether a local value can safely escape" + | Gc_ignorable_check -> + fprintf ppf "the check to see whether a value can be ignored by GC" + | Separability_check -> + fprintf ppf "the check that a type is definitely not `float`" + + let format_value_creation_reason ppf : value_creation_reason -> _ = function + | Class_let_binding -> fprintf ppf "let-bound in a class expression" + | Tuple_element -> fprintf ppf "a tuple element" + | Probe -> fprintf ppf "a probe" + | Package_hack -> fprintf ppf "used as an element in a first-class module" + | Object -> fprintf ppf "an object" + | Instance_variable -> fprintf ppf "an instance variable" + | Object_field -> fprintf ppf "an object field" + | Class_field -> fprintf ppf "an class field" + | Boxed_record -> fprintf ppf "a boxed record" + | Boxed_variant -> fprintf ppf "a boxed variant" + | Extensible_variant -> fprintf ppf "an extensible variant" + | Primitive id -> + fprintf ppf "it equals the primitive value type %s" (Ident.name id) + | Type_argument -> fprintf ppf "a type argument defaulted to have layout value" + | Tuple -> fprintf ppf "a tuple type" + | Row_variable -> fprintf ppf "a row variable" + | Polymorphic_variant -> fprintf ppf "a polymorphic variant" + | Arrow -> fprintf ppf "a function type" + | Tfield -> fprintf ppf "an internal Tfield type (you shouldn't see this)" + | Tnil -> fprintf ppf "an internal Tnil type (you shouldn't see this)" + | First_class_module -> fprintf ppf "a first-class module type" + | Separability_check -> + fprintf ppf "the check that a type is definitely not `float`" + | Univar -> fprintf ppf "an unannotated universal variable" + | Polymorphic_variant_field -> fprintf ppf "a field of a polymorphic variant" + | Default_type_layout -> + fprintf ppf "the default layout for an abstract type" + | Float_record_field -> + fprintf ppf "a field of a float record" + | Existential_type_variable -> + fprintf ppf "an unannotated existential type variable" + | Array_element -> + fprintf ppf "an array element" + | Lazy_expression -> + fprintf ppf "a lazy expression" + | Class_argument -> + fprintf ppf "a term-level argument to a class constructor" + | Structure_element -> + fprintf ppf "stored in a module structure" + | Debug_printer_argument -> + fprintf ppf "used as the argument to a debugger printer function" | V1_safety_check -> fprintf ppf "to be value for the V1 safety check" - | Dummy_reason_result_ignored -> - Misc.fatal_errorf - "Found [Dummy_reason_result_ignored] in a [layout] when printing!" - - let format_history ~pp_name ~name ppf t = - (* CR layouts: Re-do this whole facility with a tree structure *) - if false then begin - let message ppf = function - | 0 -> fprintf ppf "%a's layout was constrained" pp_name name - | _ -> fprintf ppf "and" + | Unknown s -> fprintf ppf "unknown @[(please alert the Jane Street@;\ + compilers team with this message: %s)@]" s + + + let format_void_creation_reason ppf : void_creation_reason -> _ = function + | V1_safety_check -> fprintf ppf "check to make sure there are no voids" + (* CR layouts: remove this when we remove its uses *) + + let format_creation_reason ppf : creation_reason -> unit = function + | Annotated (ctx, _) -> + fprintf ppf "of the annotation on %a" format_annotation_context ctx + | Any_creation any -> + format_any_creation_reason ppf any + | Immediate_creation immediate -> + format_immediate_creation_reason ppf immediate + | Immediate64_creation immediate64 -> + format_immediate64_creation_reason ppf immediate64 + | Void_creation void -> + format_void_creation_reason ppf void + | Value_creation value -> + format_value_creation_reason ppf value + | Concrete_creation concrete -> + format_concrete_layout_reason ppf concrete + | Imported -> + fprintf ppf "imported from another compilation unit" + + let format_interact_reason ppf = function + | Gadt_equation name -> + fprintf ppf "a GADT match on the constructor %a" !printtyp_path name + | Tyvar_refinement_intersection -> + fprintf ppf "updating a type variable" + | Sublayout -> + fprintf ppf "sublayout check" + + (* a flattened_history describes the history of a layout L. That + layout has been constrained to be a sublayout of layouts L1..Ln. + Each element in a flattened_history includes a layout desc Li and the + set of circumstances that gave rise to a constraint of that layout. + Any layouts Lk such that an Li < Lk doesn't contribute to the choice + of L and is thus omitted from a flattened_history. + + INVARIANT: the creation_reasons within a list all are reasons for + the layout they are paired with. + INVARIANT: L is a sublayout of all the Li in a flattened_history. + INVARIANT: If Li and Lj are stored in different entries in a + flattened_history, then not (Li <= Lj) and not (Lj <= Li). + This implies that no two elements in a flattened_history have the + same layout in them. + INVARIANT: no list in this structure is empty + + Both levels of list are unordered. + + Because a flattened_history stores [desc]s, it should be discarded + promptly after use. + + This type could be more efficient in several ways, but there is + little incentive to do so. *) + type flattened_row = desc * creation_reason list + type flattened_history = flattened_row list + + (* first arg is the layout L whose history we are flattening *) + let flatten_history : internal -> history -> flattened_history = + let add layout reason = + let layout_desc = get_internal layout in + let rec go acc = function + | ((key, value) as row) :: rest -> + begin match sub_desc layout_desc key with + | Sub -> go acc rest + | Equal -> (key, reason :: value) :: acc @ rest + | Not_sub -> go (row :: acc) rest + end + | [] -> (layout_desc, [reason]) :: acc + in + go [] + in + let rec history acc internal = function + | Interact { reason = _ + ; lhs_layout + ; lhs_history + ; rhs_layout + ; rhs_history } -> + let fh1 = history acc lhs_layout lhs_history in + let fh2 = history fh1 rhs_layout rhs_history in + fh2 + | Creation reason -> + add internal reason acc in - List.iteri - (fun i r -> - fprintf ppf "@,@[%a %a@]" - message i - format_reason r) - t.history + fun internal hist -> + history [] internal hist + + let format_flattened_row ppf (lay, reasons) = + fprintf ppf "%a, because" format_desc lay; + match reasons with + | [reason] -> fprintf ppf "@ %a." format_creation_reason reason + | _ -> + fprintf ppf " all of the following:@ @[ %a@]" + (pp_print_list format_creation_reason) reasons + + let format_flattened_history ~intro ppf t = + let fh = flatten_history t.layout t.history in + fprintf ppf "@[%t " intro; + begin match fh with + | [row] -> format_flattened_row ppf row + | _ -> fprintf ppf "a sublayout of all of the following:@ @[ %a@]" + (pp_print_list format_flattened_row) fh + end; + fprintf ppf "@]@;" + + (* this isn't really formatted for user consumption *) + let format_history_tree ~intro ppf t = + let rec in_order ppf = function + | Interact { reason; lhs_history; rhs_history } -> + fprintf ppf "@[ %a@]@;%a@ @[ %a@]" + in_order lhs_history + format_interact_reason reason + in_order rhs_history + | Creation c -> + format_creation_reason ppf c + in + fprintf ppf "@;%t has this layout history:@;@[ %a@]" + intro + in_order t.history + + let format_history ~intro ppf t = + if display_histories then begin + if flattened_histories + then format_flattened_history ~intro ppf t + else format_history_tree ~intro ppf t end end - include Formatting + include Format_history (******************************) (* errors *) @@ -424,125 +792,64 @@ module Layout = struct module Violation = struct open Format - let printtyp_path = ref (fun _ _ -> assert false) - - let set_printtyp_path f = printtyp_path := f - - type message = + type violation = | Not_a_sublayout of t * t | No_intersection of t * t - type violation = - { message : message - ; missing_cmi : bool } - - let derive_missing_cmi l1 l2 = - let missing_cmi l = - match l.layout with - | Any { missing_cmi_for = Some _ } -> - true - | Any { missing_cmi_for = None } | Sort _ | Immediate64 | Immediate -> - false - in - missing_cmi l1 || missing_cmi l2 - - let not_a_sublayout l1 l2 = - { message = Not_a_sublayout (l1, l2) - ; missing_cmi = derive_missing_cmi l1 l2 - } - - let no_intersection l1 l2 = - { message = No_intersection (l1, l2) - ; missing_cmi = derive_missing_cmi l1 l2 - } - - let add_missing_cmi_for ~missing_cmi_for = function - | { layout = Any { missing_cmi_for = None }; history } -> - { layout = Any { missing_cmi_for = Some missing_cmi_for }; history } - | t -> t - - let add_missing_cmi_for_lhs ~missing_cmi_for t = - { message = begin match t.message with - | Not_a_sublayout (lhs, rhs) -> - Not_a_sublayout (add_missing_cmi_for ~missing_cmi_for lhs, rhs) - | No_intersection (lhs, rhs) -> - No_intersection (add_missing_cmi_for ~missing_cmi_for lhs, rhs) - end - ; missing_cmi = true - (* CR layouts: If we decide to keep the [missing_cmi] field, we should - think about whether this function ought to check if - [add_missing_cmi_for] did anything. *) - } + type nonrec t = { violation : violation + ; missing_cmi : Path.t option } + (* [missing_cmi]: is this error a result of a missing cmi file? + This is stored separately from the [violation] because it's + used to change the behavior of [value_kind], and we don't + want that function to inspect something that is purely about + the choice of error message. (Though the [Path.t] payload *is* + indeed just about the payload.) *) - let missing_cmi_hint ppf type_path = - let root_module_name p = p |> Path.head |> Ident.name in - let delete_trailing_double_underscore s = - if Misc.Stdlib.String.ends_with ~suffix:"__" s - then String.sub s 0 (String.length s - 2) - else s - in - (* A heuristic for guessing at a plausible library name for an identifier - with a missing .cmi file; definitely less likely to be right outside of - Jane Street. *) - let guess_library_name : Path.t -> string option = function - | Pdot _ as p -> Some begin - match root_module_name p with - | "Location" | "Longident" -> "ocamlcommon" - | mn -> mn - |> String.lowercase_ascii - |> delete_trailing_double_underscore - end - | Pident _ | Papply _ -> - None - in - Option.iter - (fprintf ppf "@,Hint: Adding \"%s\" to your dependencies might help.") - (guess_library_name type_path) + let of_ violation = { violation; missing_cmi = None } - let report_missing_cmi ppf = function - | { layout = Any { missing_cmi_for = Some p }; _ } -> - fprintf ppf "@,No .cmi file found containing %a.%a" - (!printtyp_path) p - missing_cmi_hint p - | _ -> () - - type problem = - | Is_not_representable - | Is_not_a_sublayout_of - | Does_not_overlap_with - - let message = function - | Is_not_representable -> "is not representable" - | Is_not_a_sublayout_of -> "is not a sublayout of" - | Does_not_overlap_with -> "does not overlap with" - - let report_second = function - | Is_not_representable -> - fun _ _ -> () - | Is_not_a_sublayout_of | Does_not_overlap_with -> - fun ppf -> fprintf ppf " %a" format + let record_missing_cmi ~missing_cmi_for t = { t with missing_cmi = Some missing_cmi_for } + + let is_missing_cmi { missing_cmi } = Option.is_some missing_cmi let report_general preamble pp_former former ppf t = - let l1, problem, l2 = match t.message with - | Not_a_sublayout(l1, l2) -> - l1, - (match get l2 with - | Var _ -> Is_not_representable - | Const _ -> Is_not_a_sublayout_of), - l2 - | No_intersection(l1, l2) -> - l1, Does_not_overlap_with, l2 + let sublayout_format verb l2 = match get l2 with + | Var _ -> dprintf "%s representable" verb + | Const _ -> dprintf "%s a sublayout of %a" verb format l2 + in + let l1, l2, fmt_l1, fmt_l2, missing_cmi_option = match t with + | { violation = Not_a_sublayout(l1, l2); missing_cmi } -> + begin match missing_cmi with + | None -> + l1, l2, + dprintf "layout %a" format l1, + sublayout_format "is not" l2, None + | Some p -> + l1, l2, + dprintf "an unknown layout", + sublayout_format "might not be" l2, Some p + end + | { violation = No_intersection(l1, l2); missing_cmi } -> + assert (Option.is_none missing_cmi); + l1, l2, + dprintf "layout %a" format l1, + dprintf "does not overlap with %a" format l2, None in - fprintf ppf "@[@[%s%a has layout %a,@ which %s%a.@]%a%a%a%a@]" - preamble - pp_former former - format l1 - (message problem) - (report_second problem) l2 - (format_history ~pp_name:pp_former ~name:former) l1 - (format_history ~pp_name:pp_print_string ~name:"The latter") l2 - report_missing_cmi l1 - report_missing_cmi l2 + if display_histories then begin + let connective = match t.violation with + | Not_a_sublayout _ -> "be a sublayout of" + | No_intersection _ -> "overlap with" + in + fprintf ppf "%a%a" + (format_history ~intro:(dprintf "The layout of %a is" pp_former former)) l1 + (format_history ~intro:(dprintf "But the layout of %a must %s" pp_former former connective)) l2; + end else begin + fprintf ppf "@[%s%a has %t,@ which %t.@]" + preamble + pp_former former + fmt_l1 + fmt_l2 + end; + report_missing_cmi ppf missing_cmi_option let pp_t ppf x = fprintf ppf "%t" x @@ -554,14 +861,14 @@ module Layout = struct let report_with_name ~name = report_general "" pp_print_string name -end + end (******************************) (* relations *) let equate_or_equal ~allow_mutation (l1 : t) (l2 : t) = match l1.layout, l2.layout with - | Any _, Any _ -> true + | Any, Any -> true | Immediate64, Immediate64 -> true | Immediate, Immediate -> true | Sort s1, Sort s2 -> begin @@ -573,42 +880,74 @@ end | Unequal -> false | Equal_no_mutation | Equal_mutated_first | Equal_mutated_second -> true end - | (Any _ | Immediate64 | Immediate | Sort _), _ -> false + | (Any | Immediate64 | Immediate | Sort _), _ -> false (* CR layouts v2: Switch this back to ~allow_mutation:false *) let equal = equate_or_equal ~allow_mutation:true let equate = equate_or_equal ~allow_mutation:true + let combine_histories reason lhs rhs = + Interact { reason; lhs_layout = lhs.layout; lhs_history = lhs.history; + rhs_layout = rhs.layout; rhs_history = rhs.history } + let intersection ~reason l1 l2 = - let err = Error (Violation.no_intersection l1 l2) in - let equality_check is_eq l = if is_eq then Ok l else err in - (* it's OK not to cache the result of [get], because [get] does path - compression *) - Result.map (add_reason reason) @@ match get l1, get l2 with - | Const Any, _ -> Ok { layout = l2.layout; history = l1.history } - | _, Const Any -> Ok l1 - | Const c1, Const c2 when equal_const c1 c2 -> Ok l1 - | Const (Immediate64 | Immediate), Const (Immediate64 | Immediate) -> - Ok immediate - | Const ((Immediate64 | Immediate) as imm), l - | l, Const ((Immediate64 | Immediate) as imm) -> - equality_check (equate (of_desc l) value) - (of_const imm) - | _, _ -> equality_check (equate l1 l2) l1 - - let sub sub super = - let ok = Ok () in - let equality_check is_eq = if is_eq then ok - else Error (Violation.not_a_sublayout sub super) - in - match get sub, get super with - | _, Const Any -> ok - | Const c1, Const c2 when equal_const c1 c2 -> ok - | Const Immediate, Const Immediate64 -> ok - | Const (Immediate64 | Immediate), _ -> - equality_check (equate super value) - | _, _ -> equality_check (equate sub super) + match l1.layout, l2.layout with + (* only update the history when something interesting happens; e.g. + finding the intersection between a sublayout and its superlayout + is not interesting *) + | _, Any -> Ok l1 + | Any, _ -> Ok l2 + | (Immediate, Immediate) | (Immediate64, Immediate64) -> + Ok { l1 with history = combine_histories reason l1 l2 } + | Immediate, Immediate64 -> Ok l1 + | Immediate64, Immediate -> Ok l2 + | (Immediate | Immediate64), Sort s -> + if Sort.equate s Sort.value + then Ok l1 + else Error (Violation.of_ (No_intersection (l1, l2))) + | Sort s, (Immediate | Immediate64) -> + if Sort.equate s Sort.value + then Ok l2 + else Error (Violation.of_ (No_intersection (l1, l2))) + | Sort s1, Sort s2 -> + if Sort.equate s1 s2 + then Ok { l1 with history = combine_histories reason l1 l2 } + else Error (Violation.of_ (No_intersection (l1, l2))) + + (* this is hammered on; it must be fast! *) + let check_sub sub super : sub_result = + match sub.layout, super.layout with + (* don't use [get], because that allocates *) + | Any, Any -> Equal + | _, Any -> Sub + | Immediate, Immediate -> Equal + | Immediate64, Immediate64 -> Equal + | Immediate, Immediate64 -> Sub + | Immediate64, Immediate -> Not_sub + | (Immediate | Immediate64), Sort s -> + if Sort.equate s Sort.value then Sub else Not_sub + | Sort s1, Sort s2 -> + if Sort.equate s1 s2 then Equal else Not_sub + | Any, _ -> Not_sub + | Sort _, (Immediate | Immediate64) -> Not_sub + + let sub sub super = match check_sub sub super with + | Sub | Equal -> Ok () + | Not_sub -> Error (Violation.of_ (Not_a_sublayout (sub, super))) + + let sub_with_history sub super = match check_sub sub super with + | Sub | Equal -> + Ok { sub with history = combine_histories Sublayout sub super } + | Not_sub -> Error (Violation.of_ (Not_a_sublayout (sub, super))) + + let is_void_defaulting = function + | { layout = Sort s } -> Sort.is_void_defaulting s + | _ -> false + + let is_any = function + | { layout = Any } -> true + | _ -> false (*********************************) (* debugging *) @@ -617,23 +956,11 @@ end open Format let internal ppf : internal -> unit = function - | Any { missing_cmi_for } -> - fprintf ppf "Any { missing_cmi_for = %a }" - (Misc.Stdlib.Option.print Path.print) missing_cmi_for + | Any -> fprintf ppf "Any" | Sort s -> fprintf ppf "Sort %a" Sort.Debug_printers.t s | Immediate64 -> fprintf ppf "Immediate64" | Immediate -> fprintf ppf "Immediate" - let fixed_layout_reason ppf : fixed_layout_reason -> unit = function - | Let_binding -> fprintf ppf "Let_binding" - | Tuple_element -> fprintf ppf "Tuple_element" - | Probe -> fprintf ppf "Probe" - | Package_hack -> fprintf ppf "Package_hack" - | Object -> fprintf ppf "Object" - | Instance_variable -> fprintf ppf "Instance_variable" - | Object_field -> fprintf ppf "Object_field" - | Class_field -> fprintf ppf "Class_field" - let concrete_layout_reason ppf : concrete_layout_reason -> unit = function | Match -> fprintf ppf "Match" @@ -641,44 +968,144 @@ end fprintf ppf "Constructor_declaration %d" idx | Label_declaration lbl -> fprintf ppf "Label_declaration %a" Ident.print lbl - | Function_argument -> fprintf ppf "Function_argument" - | Function_result -> fprintf ppf "Function_result" + | Unannotated_type_parameter -> + fprintf ppf "Unannotated_type_parameter" + | Record_projection -> + fprintf ppf "Record_projection" + | Record_assignment -> + fprintf ppf "Record_assignment" + | Let_binding -> + fprintf ppf "Let_binding" + | Function_argument -> + fprintf ppf "Function_argument" + | Function_result -> + fprintf ppf "Function_result" + | Structure_item_expression -> + fprintf ppf "Structure_item_expression" + | V1_safety_check -> + fprintf ppf "V1_safety_check" - let annotation_location ppf : annotation_location -> unit = function + let annotation_context ppf : annotation_context -> unit = function | Type_declaration p -> fprintf ppf "Type_declaration %a" Path.print p | Type_parameter (p, var) -> fprintf ppf "Type_parameter (%a, %S)" Path.print p var - | With_constraint loc -> - fprintf ppf "With_constraint %a" Location.print_loc loc - | Newtype_declaration {loc; txt} -> - fprintf ppf "Newtype_declaration %s@@%a" txt Location.print_loc loc - - let reason ppf : reason -> unit = function - | Fixed_layout flr -> - fprintf ppf "Fixed_layout %a" fixed_layout_reason flr - | Concrete_layout clr -> - fprintf ppf "Concrete_layout %a" concrete_layout_reason clr - | Annotated aloc -> - fprintf ppf "Annotated %a" annotation_location aloc + | With_constraint s -> + fprintf ppf "With_constraint %S" s + | Newtype_declaration name -> + fprintf ppf "Newtype_declaration %s" name + + let any_creation_reason ppf : any_creation_reason -> unit = function + | Missing_cmi p -> fprintf ppf "Missing_cmi %a" Path.print p + | Wildcard -> fprintf ppf "Wildcard" + | Unification_var -> fprintf ppf "Unification_var" + | Initial_typedecl_env -> fprintf ppf "Initial_typedecl_env" + | Dummy_layout -> fprintf ppf "Dummy_layout" + | Type_expression_call -> fprintf ppf "Type_expression_call" + + let immediate_creation_reason ppf : immediate_creation_reason -> _ = + function + | Empty_record -> fprintf ppf "Empty_record" + | Enumeration -> fprintf ppf "Enumeration" + | Primitive id -> fprintf ppf "Primitive %s" (Ident.unique_name id) + | Immediate_polymorphic_variant -> + fprintf ppf "Immediate_polymorphic_variant" + | Gc_ignorable_check -> fprintf ppf "Gc_ignorable_check" + | Value_kind -> fprintf ppf "Value_kind" + + let immediate64_creation_reason ppf = function + | Local_mode_cross_check -> fprintf ppf "Local_mode_cross_check" + | Gc_ignorable_check -> fprintf ppf "Gc_ignorable_check" + | Separability_check -> fprintf ppf "Separability_check" + + let value_creation_reason ppf : value_creation_reason -> _ = function + | Class_let_binding -> fprintf ppf "Class_let_binding" + | Tuple_element -> fprintf ppf "Tuple_element" + | Probe -> fprintf ppf "Probe" + | Package_hack -> fprintf ppf "Package_hack" + | Object -> fprintf ppf "Object" + | Instance_variable -> fprintf ppf "Instance_variable" + | Object_field -> fprintf ppf "Object_field" + | Class_field -> fprintf ppf "Class_field" + | Boxed_record -> fprintf ppf "Boxed_record" + | Boxed_variant -> fprintf ppf "Boxed_variant" + | Extensible_variant -> fprintf ppf "Extensible_variant" + | Primitive id -> fprintf ppf "Primitive %s" (Ident.unique_name id) + | Type_argument -> fprintf ppf "Type_argument" + | Tuple -> fprintf ppf "Tuple" + | Row_variable -> fprintf ppf "Row_variable" + | Polymorphic_variant -> fprintf ppf "Polymorphic_variant" + | Arrow -> fprintf ppf "Arrow" + | Tfield -> fprintf ppf "Tfield" + | Tnil -> fprintf ppf "Tnil" + | First_class_module -> fprintf ppf "First_class_module" + | Separability_check -> fprintf ppf "Separability_check" + | Univar -> fprintf ppf "Univar" + | Polymorphic_variant_field -> fprintf ppf "Polymorphic_variant_field" + | Default_type_layout -> fprintf ppf "Default_type_layout" + | Float_record_field -> fprintf ppf "Float_record_field" + | Existential_type_variable -> fprintf ppf "Existential_type_variable" + | Array_element -> fprintf ppf "Array_element" + | Lazy_expression -> fprintf ppf "Lazy_expression" + | Class_argument -> fprintf ppf "Class_argument" + | Structure_element -> fprintf ppf "Structure_element" + | Debug_printer_argument -> fprintf ppf "Debug_printer_argument" + | V1_safety_check -> fprintf ppf "V1_safety_check" + | Unknown s -> fprintf ppf "Unknown %s" s + + let void_creation_reason ppf : void_creation_reason -> _ = function + | V1_safety_check -> fprintf ppf "V1_safety_check" + + let creation_reason ppf : creation_reason -> unit = function + | Annotated (ctx, loc) -> + fprintf ppf "Annotated (%a,%a)" + annotation_context ctx + Location.print_loc loc + | Any_creation any -> + fprintf ppf "Any_creation %a" any_creation_reason any + | Immediate_creation immediate -> + fprintf ppf "Immediate_creation %a" immediate_creation_reason immediate + | Immediate64_creation immediate64 -> + fprintf ppf "Immediate64_creation %a" immediate64_creation_reason immediate64 + | Value_creation value -> + fprintf ppf "Value_creation %a" value_creation_reason value + | Void_creation void -> + fprintf ppf "Void_creation %a" void_creation_reason void + | Concrete_creation concrete -> + fprintf ppf "Concrete_creation %a" concrete_layout_reason concrete + | Imported -> + fprintf ppf "Imported" + + let interact_reason ppf = function | Gadt_equation p -> - fprintf ppf "Gadt_equation %a" Path.print p - | Unified_with_tvar tv -> - fprintf ppf "Unified_with_tvar %a" - (Misc.Stdlib.Option.print pp_print_string) tv - | V1_safety_check -> - fprintf ppf "V1_safety_check" - | Dummy_reason_result_ignored -> - fprintf ppf "Dummy_reason_result_ignored" - - let reasons ppf (rs : reason list) : unit = - fprintf ppf "@[[ %a@]@,]" - (pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf "@,; ") reason) rs - - let t ppf ({ layout; history } : t) : unit = + fprintf ppf "Gadt_equation %a" + Path.print p + | Tyvar_refinement_intersection -> + fprintf ppf "Tyvar_refinement_intersection" + | Sublayout -> + fprintf ppf "Sublayout" + + let rec history ppf = function + | Interact + { reason; lhs_layout; lhs_history; rhs_layout; rhs_history } -> + fprintf ppf "Interact {@[reason = %a;@ \ + lhs_layout = %a;@ \ + lhs_history = %a;@ \ + rhs_layout = %a;@ \ + rhs_history = %a}@]" + interact_reason reason + internal lhs_layout + history lhs_history + internal rhs_layout + history rhs_history + | Creation c -> + fprintf ppf "Creation (%a)" + creation_reason c + + let t ppf ({ layout; history=h } : t) : unit = fprintf ppf "@[{ layout = %a@,; history = %a }@]" internal layout - reasons history + history h end end diff --git a/ocaml/typing/layouts.mli b/ocaml/typing/layouts.mli index 5fda4cd1539..6ca1f98d43a 100644 --- a/ocaml/typing/layouts.mli +++ b/ocaml/typing/layouts.mli @@ -45,6 +45,15 @@ module Sort : sig equal, if possible *) val equate : t -> t -> bool + val format : Format.formatter -> t -> unit + + (** Defaults any variables to value; leaves other sorts alone *) + val default_to_value : t -> unit + + (** Checks whether this sort is [void], defaulting to [value] if a sort + variable is unfilled. *) + val is_void_defaulting : t -> bool + module Debug_printers : sig val t : Format.formatter -> t -> unit val var : Format.formatter -> var -> unit @@ -72,107 +81,120 @@ module Layout : sig [Any] and sublayouts of other sorts, such as [Immediate]. *) type t - (******************************) - (* constants *) - - (** Constant layouts are used both for user-written annotations and within - the type checker when we know a layout has no variables *) - type const = Asttypes.const_layout = - | Any - | Value - | Void - | Immediate64 - | Immediate - val string_of_const : const -> string - val equal_const : const -> const -> bool - - (** This layout is the top of the layout lattice. All types have layout [any]. - But we cannot compile run-time manipulations of values of types with - layout [any]. *) - val any : t - - (** This is a variant of the [any] layout used when we have to fill it in - because there's a missing .cmi file for the specified type. *) - val missing_cmi_any : Path.t -> t - - (** Value of types of this layout are not retained at all at runtime *) - val void : t - - (** This is the layout of normal ocaml values *) - val value : t - - (** Values of types of this layout are immediate on 64-bit platforms; on other - platforms, we know nothing other than that it's a value. *) - val immediate64 : t - - (** We know for sure that values of types of this layout are always immediate *) - val immediate : t - (******************************) (* errors *) - type fixed_layout_reason = - | Let_binding - | Tuple_element - | Probe - | Package_hack - | Object - | Instance_variable - | Object_field - | Class_field - type concrete_layout_reason = | Match | Constructor_declaration of int | Label_declaration of Ident.t + | Unannotated_type_parameter + | Record_projection + | Record_assignment + | Let_binding | Function_argument | Function_result + | Structure_item_expression + | V1_safety_check - type annotation_location = + type annotation_context = | Type_declaration of Path.t | Type_parameter of Path.t * string - | With_constraint of Location.t - | Newtype_declaration of string Location.loc + | With_constraint of string + | Newtype_declaration of string - type reason = - | Fixed_layout of fixed_layout_reason - | Concrete_layout of concrete_layout_reason - | Annotated of annotation_location - | Gadt_equation of Path.t - | Unified_with_tvar of string option - (* CR layouts v2: This really needs to carry a type, in case it - gets further unified. But that makes layouts recursive with - types, which will involve a painful restructuring. Still, RAE - thinks it's inevitable. *) + type value_creation_reason = + | Class_let_binding + | Tuple_element + | Probe + | Package_hack + | Object + | Instance_variable + | Object_field + | Class_field + | Boxed_record + | Boxed_variant + | Extensible_variant + | Primitive of Ident.t + | Type_argument (* CR layouts: Should this take a Path.t? *) + | Tuple + | Row_variable + | Polymorphic_variant + | Arrow + | Tfield + | Tnil + | First_class_module + | Separability_check + | Univar + | Polymorphic_variant_field + | Default_type_layout + | Float_record_field + | Existential_type_variable + | Array_element + | Lazy_expression + | Class_argument + | Structure_element + | Debug_printer_argument | V1_safety_check - | Dummy_reason_result_ignored + | Unknown of string (* CR layouts: get rid of these *) + + type immediate_creation_reason = + | Empty_record + | Enumeration + | Primitive of Ident.t + | Immediate_polymorphic_variant + | Gc_ignorable_check + | Value_kind + + type immediate64_creation_reason = + | Local_mode_cross_check + | Gc_ignorable_check + | Separability_check + + type void_creation_reason = + | V1_safety_check + + type any_creation_reason = + | Missing_cmi of Path.t + | Wildcard + | Unification_var + | Initial_typedecl_env + | Dummy_layout + (* This is used when the layout is about to get overwritten; + key example: when creating a fresh tyvar that is immediately + unified to correct levels *) + | Type_expression_call + + type creation_reason = + | Annotated of annotation_context * Location.t + | Value_creation of value_creation_reason + | Immediate_creation of immediate_creation_reason + | Immediate64_creation of immediate64_creation_reason + | Void_creation of void_creation_reason + | Any_creation of any_creation_reason + | Concrete_creation of concrete_layout_reason + | Imported + + type interact_reason = + | Gadt_equation of Path.t + | Tyvar_refinement_intersection + (* CR layouts: this needs to carry a type_expr, but that's loopy *) + | Sublayout module Violation : sig - type message = + type violation = | Not_a_sublayout of t * t | No_intersection of t * t - type violation = private - { message : message - ; missing_cmi : bool - (** Was this error caused by a missing .cmi file? This is redundant - with information stored in the [message], but is more easily - inspectable by external code. The error-printing code does not - inspect this value; it's only used for program logic. *) - } + type t - val not_a_sublayout : t -> t -> violation + val of_ : violation -> t - val no_intersection : t -> t -> violation + (** Mark a [t] as having arisen from a missing cmi *) + val record_missing_cmi : missing_cmi_for:Path.t -> t -> t - (* CR layouts: Is [missing_cmi] really the best thing? Maybe some functions - need to return success | error | missing_cmi. *) - - (** If we later discover that the left-hand layout was from a missing .cmi - file, and if that layout is [any], this function will update that layout - to report what type caused that (a la [missing_cmi_any]). *) - val add_missing_cmi_for_lhs : - missing_cmi_for:Path.t -> violation -> violation + (** Is this error from a missing cmi? *) + val is_missing_cmi : t -> bool (* CR layouts: The [offender] arguments below are always [Printtyp.type_expr], so we should either stash that in a ref (like with @@ -186,54 +208,87 @@ module Layout : sig ([offender], which you supply an arbitrary printer for). *) val report_with_offender : offender:(Format.formatter -> unit) -> - Format.formatter -> violation -> unit + Format.formatter -> t -> unit (** Like [report_with_offender], but additionally prints that the issue is that a representable layout was expected. *) val report_with_offender_sort : offender:(Format.formatter -> unit) -> - Format.formatter -> violation -> unit + Format.formatter -> t -> unit (** Simpler version of [report_with_offender] for when the thing that had an unexpected layout is available as a string. *) - val report_with_name : name:string -> Format.formatter -> violation -> unit - - (** Provides the [Printtyp.path] formatter back up the dependency chain to - this module. *) - val set_printtyp_path : (Format.formatter -> Path.t -> unit) -> unit + val report_with_name : name:string -> Format.formatter -> t -> unit end + (******************************) + (* constants *) + + (** Constant layouts are used both for user-written annotations and within + the type checker when we know a layout has no variables *) + type const = Asttypes.const_layout = + | Any + | Value + | Void + | Immediate64 + | Immediate + val string_of_const : const -> string + val equal_const : const -> const -> bool + + (** This layout is the top of the layout lattice. All types have layout [any]. + But we cannot compile run-time manipulations of values of types with layout + [any]. *) + val any : why:any_creation_reason -> t + + (** Value of types of this layout are not retained at all at runtime *) + val void : why:void_creation_reason -> t + + (** This is the layout of normal ocaml values *) + val value : why:value_creation_reason -> t + + (** Values of types of this layout are immediate on 64-bit platforms; on other + platforms, we know nothing other than that it's a value. *) + val immediate64 : why:immediate64_creation_reason -> t + + (** We know for sure that values of types of this layout are always immediate *) + val immediate : why:immediate_creation_reason -> t + (******************************) (* construction *) (** Create a fresh sort variable, packed into a layout. *) - val of_new_sort_var : unit -> t + val of_new_sort_var : why:concrete_layout_reason -> t - val of_sort : sort -> t - val of_const : const -> t + val of_sort : why:concrete_layout_reason -> sort -> t + val of_const : why:creation_reason -> const -> t (** Find a layout in attributes. Returns error if a disallowed layout is present, but always allows immediate attributes if ~legacy_immediate is true. See comment on [Builtin_attributes.layout]. *) val of_attributes : - legacy_immediate:bool -> reason:annotation_location -> Parsetree.attributes -> - (t option, Location.t * const) result + legacy_immediate:bool -> reason:annotation_context -> Parsetree.attributes -> + (t option, const Location.loc) result (** Find a layout in attributes, defaulting to ~default. Returns error if a disallowed layout is present, but always allows immediate if ~legacy_immediate is true. See comment on [Builtin_attributes.layout]. *) val of_attributes_default : - legacy_immediate:bool -> reason:annotation_location -> + legacy_immediate:bool -> reason:annotation_context -> default:t -> Parsetree.attributes -> - (t, Location.t * const) result + (t, const Location.loc) result (** Choose an appropriate layout for a boxed record type, given whether all of its fields are [void]. *) val for_boxed_record : all_void:bool -> t + (** Choose an appropriate layout for a boxed variant type, given whether + all of the fields of all of its constructors are [void]. *) + val for_boxed_variant : all_voids:bool -> t + (******************************) (* elimination and defaulting *) + (* The description of a layout, used as a return type from [get]. *) type desc = | Const of const | Var of Sort.var @@ -252,13 +307,11 @@ module Layout : sig (** [is_void t] is [Void = get_default_value t]. In particular, it will default the layout to value if needed to make this false. *) - val is_void : t -> bool + val is_void_defaulting : t -> bool (* CR layouts v5: When we have proper support for void, we'll want to change these three functions to default to void - it's the most efficient thing when we have a choice. *) - val of_desc : desc -> t - (** Returns the sort corresponding to the layout. Call only on representable layouts - raises on Any. *) val sort_of_layout : t -> sort @@ -268,10 +321,20 @@ module Layout : sig val to_string : t -> string val format : Format.formatter -> t -> unit + + (** Format the history of this layout: what interactions it has had and why + it is the layout that it is. Might be a no-op: see [display_histories] + in the implementation of the [Layout] module. + + The [intro] is something like "The layout of t is". *) val format_history : - pp_name:(Format.formatter -> 'a -> unit) -> name:'a -> + intro:(Format.formatter -> unit) -> Format.formatter -> t -> unit + (** Provides the [Printtyp.path] formatter back up the dependency chain to + this module. *) + val set_printtyp_path : (Format.formatter -> Path.t -> unit) -> unit + (******************************) (* relations *) @@ -286,33 +349,33 @@ module Layout : sig when there is no need for unification; e.g. [equal] on a var and [value] will crash. - This function ignores the [missing_cmi_for] medatadata for [any]s. - - CR layouts v2: At the moment, this is actually the same as [equate]! Fix. *) + CR layouts (v1.5): At the moment, this is actually the same as [equate]! *) val equal : t -> t -> bool (** Finds the intersection of two layouts, constraining sort variables to - create one if needed, or returns a [Violation.violation] if an - intersection does not exist. Can update the layouts. The returned - layout's history consists of the provided reason followed by the history - of the first layout argument. That is, due to histories, this function is - asymmetric; it should be thought of as modifying the first layout to be - the intersection of the two, not something that modifies the second - layout. *) + create one if needed, or returns a [Violation.t] if an intersection does + not exist. Can update the layouts. The returned layout's history + consists of the provided reason followed by the history of the first + layout argument. That is, due to histories, this function is asymmetric; + it should be thought of as modifying the first layout to be the + intersection of the two, not something that modifies the second layout. *) val intersection : - reason:reason -> t -> t -> (t, Violation.violation) Result.t + reason:interact_reason -> t -> t -> (t, Violation.t) Result.t - (** [sub t1 t2] returns [Ok t1] iff [t1] is a sublayout of - of [t2]. The current hierarchy is: + (** [sub t1 t2] returns [Ok ()] iff [t1] is a sublayout of + of [t2]. The current hierarchy is: Any > Sort Value > Immediate64 > Immediate Any > Sort Void Returns [Error _] if the coercion is not possible. *) - val sub : t -> t -> (unit, Violation.violation) result + val sub : t -> t -> (unit, Violation.t) result - (*********************************) - (* defaulting *) + (** Like [sub], but returns the sublayout with an updated history. *) + val sub_with_history : t -> t -> (t, Violation.t) result + + (** Checks to see whether a layout is any. Never does any mutation. *) + val is_any : t -> bool (*********************************) (* debugging *) diff --git a/ocaml/typing/oprint.ml b/ocaml/typing/oprint.ml index 1c4b136f0b9..a485bf0121a 100644 --- a/ocaml/typing/oprint.ml +++ b/ocaml/typing/oprint.ml @@ -284,9 +284,7 @@ let join_modes rm1 am2 = let print_out_layout ppf = function | Olay_const lay -> fprintf ppf "%s" (Layouts.Layout.string_of_const lay) - | Olay_var v -> fprintf ppf "%s" v - (* CR layouts: We need to either give these names somehow or not print - them at all *) + | Olay_var v -> fprintf ppf "%s" v let print_out_layout_option ppf = function | None -> () diff --git a/ocaml/typing/parmatch.ml b/ocaml/typing/parmatch.ml index 9e665425dba..d0cbdc74f4e 100644 --- a/ocaml/typing/parmatch.ml +++ b/ocaml/typing/parmatch.ml @@ -734,7 +734,9 @@ let close_variant env row = (orig_name, true) fields in if not closed || name != orig_name then begin let more' = - if static then Btype.newgenty Tnil else Btype.newgenvar Layout.value + if static + then Btype.newgenty Tnil + else Btype.newgenvar (Layout.value ~why:Row_variable) in (* this unification cannot fail *) Ctype.unify env more diff --git a/ocaml/typing/predef.ml b/ocaml/typing/predef.ml index 98a52ebb499..70477d2ca62 100644 --- a/ocaml/typing/predef.ml +++ b/ocaml/typing/predef.ml @@ -142,7 +142,7 @@ and ident_some = ident_create "Some" let mk_add_type add_type ?manifest type_ident ?(kind=Type_abstract) - ?(layout=Layout.value) + ?(layout=Layout.value ~why:(Primitive type_ident)) env = let decl = {type_params = []; @@ -169,9 +169,9 @@ let common_initial_env add_type add_extension empty_env = let add_type = mk_add_type add_type and add_type1 type_ident ?(kind=fun _ -> Type_abstract) - ?(layout=Layout.value) + ?(layout=Layout.value ~why:(Primitive type_ident)) ~variance ~separability env = - let param = newgenvar Layout.value in + let param = newgenvar (Layout.value ~why:Type_argument) in let decl = {type_params = [param]; type_arity = 1; @@ -219,15 +219,15 @@ let common_initial_env add_type add_extension empty_env = |> add_type ident_bool ~kind:(variant [cstr ident_false []; cstr ident_true []] [| [| |]; [| |] |]) - ~layout:Layout.immediate - |> add_type ident_char ~layout:Layout.immediate + ~layout:(Layout.immediate ~why:Enumeration) + |> add_type ident_char ~layout:(Layout.immediate ~why:(Primitive ident_char)) |> add_type ident_exn ~kind:Type_open - ~layout:Layout.value + ~layout:(Layout.value ~why:Extensible_variant) |> add_type ident_extension_constructor |> add_type ident_float |> add_type ident_floatarray - |> add_type ident_int ~layout:Layout.immediate + |> add_type ident_int ~layout:(Layout.immediate ~why:(Primitive ident_int)) |> add_type ident_int32 |> add_type ident_int64 |> add_type1 ident_lazy_t @@ -240,40 +240,43 @@ let common_initial_env add_type add_extension empty_env = variant [cstr ident_nil []; cstr ident_cons [tvar, Unrestricted; type_list tvar, Unrestricted]] - [| [| |]; [| Layout.value; - Layout.value |] |] ) - ~layout:Layout.value + [| [| |]; [| Layout.value ~why:Type_argument; + Layout.value ~why:Boxed_variant |] |] ) + ~layout:(Layout.value ~why:Boxed_variant) |> add_type ident_nativeint |> add_type1 ident_option ~variance:Variance.covariant ~separability:Separability.Ind ~kind:(fun tvar -> variant [cstr ident_none []; cstr ident_some [tvar, Unrestricted]] - [| [| |]; [| Layout.value |] |]) - ~layout:Layout.value + [| [| |]; [| Layout.value ~why:Type_argument |] |]) + ~layout:(Layout.value ~why:Boxed_variant) |> add_type ident_string |> add_type ident_unit ~kind:(variant [cstr ident_void []] [| [| |] |]) - ~layout:Layout.immediate + ~layout:(Layout.immediate ~why:Enumeration) (* Predefined exceptions - alphabetical order *) |> add_extension ident_assert_failure [newgenty (Ttuple[type_string; type_int; type_int])] - [| Layout.value |] + [| Layout.value ~why:Tuple |] |> add_extension ident_division_by_zero [] [||] |> add_extension ident_end_of_file [] [||] - |> add_extension ident_failure [type_string] [| Layout.value |] - |> add_extension ident_invalid_argument [type_string] [| Layout.value |] + |> add_extension ident_failure [type_string] + [| Layout.value ~why:(Primitive ident_string) |] + |> add_extension ident_invalid_argument [type_string] + [| Layout.value ~why:(Primitive ident_string) |] |> add_extension ident_match_failure [newgenty (Ttuple[type_string; type_int; type_int])] - [| Layout.value |] + [| Layout.value ~why:Tuple |] |> add_extension ident_not_found [] [||] |> add_extension ident_out_of_memory [] [||] |> add_extension ident_stack_overflow [] [||] |> add_extension ident_sys_blocked_io [] [||] - |> add_extension ident_sys_error [type_string] [| Layout.value |] + |> add_extension ident_sys_error [type_string] + [| Layout.value ~why:(Primitive ident_string) |] |> add_extension ident_undefined_recursive_module [newgenty (Ttuple[type_string; type_int; type_int])] - [| Layout.value |] + [| Layout.value ~why:Tuple |] let build_initial_env add_type add_exception empty_env = let common = common_initial_env add_type add_exception empty_env in diff --git a/ocaml/typing/printtyp.ml b/ocaml/typing/printtyp.ml index 0fcb3a6a865..8573fc63499 100644 --- a/ocaml/typing/printtyp.ml +++ b/ocaml/typing/printtyp.ml @@ -467,7 +467,7 @@ let strings_of_paths namespace p = List.map (Format.asprintf "%a" !Oprint.out_ident) trees let () = Env.print_path := path -let () = Layouts.Layout.Violation.set_printtyp_path path +let () = Layouts.Layout.set_printtyp_path path (* Print a recursive annotation *) @@ -1487,7 +1487,7 @@ let rec tree_of_type_decl id decl = match Builtin_attributes.layout ~legacy_immediate:true decl.type_attributes with | Ok l -> l - | Error (_, l) -> Some l + | Error l_loc -> Some l_loc in let ty, priv, unboxed = match decl.type_kind with @@ -1519,7 +1519,7 @@ let rec tree_of_type_decl id decl = otype_params = args; otype_type = ty; otype_private = priv; - otype_layout = lay; + otype_layout = Option.map Location.get_txt lay; otype_unboxed = unboxed; otype_cstrs = constraints } @@ -1880,7 +1880,7 @@ let dummy = type_params = []; type_arity = 0; type_kind = Type_abstract; - type_layout = Layout.any; + type_layout = Layout.any ~why:Dummy_layout; type_private = Public; type_manifest = None; type_variance = []; @@ -2123,7 +2123,7 @@ let trees_of_type_expansion' | Tvar { layout; _ } | Tunivar { layout; _ } -> let olay = match Layouts.Layout.get layout with | Const clay -> Olay_const clay - | Var v -> Olay_var (Sort.var_name v) + | Var v -> Olay_var (Sort.var_name v) in Otyp_layout_annot (out, olay) | _ -> @@ -2244,7 +2244,8 @@ let hide_variant_name t = newty2 ~level:(get_level t) (Tvariant (create_row ~fields ~fixed ~closed ~name:None - ~more:(newvar2 (get_level more) Layout.value))) + ~more:(newvar2 (get_level more) + (Layout.value ~why:Row_variable)))) | _ -> t let prepare_expansion Errortrace.{ty; expanded} = @@ -2454,7 +2455,9 @@ let explanation (type variety) intro prev env (Layout.Violation.report_with_offender_sort ~offender:(fun ppf -> type_expr ppf t)) e) | Errortrace.Unequal_var_layouts (t1,l1,t2,l2) -> - let fmt_history t = Layout.format_history ~pp_name:type_expr ~name:t in + let fmt_history t = + Layout.format_history ~intro:(fun ppf -> type_expr ppf t) + in Some (dprintf "@ because their layouts are different.@[%a%a@]" (fmt_history t1) l1 (fmt_history t2) l2) diff --git a/ocaml/typing/printtyped.ml b/ocaml/typing/printtyped.ml index 97ac8abfca3..5a882d80b04 100644 --- a/ocaml/typing/printtyped.ml +++ b/ocaml/typing/printtyped.ml @@ -399,7 +399,7 @@ and expression i ppf x = | Texp_match (e, sort, l, _partial) -> line i ppf "Texp_match\n"; expression i ppf e; - line i ppf "%a\n" Layouts.Layout.format (Layouts.Layout.of_sort sort); + line i ppf "%a\n" Layouts.Sort.format sort; list i case ppf l; | Texp_try (e, l) -> line i ppf "Texp_try\n"; @@ -917,7 +917,7 @@ and structure_item i ppf x = | Tstr_eval (e, l, attrs) -> line i ppf "Tstr_eval\n"; attributes i ppf attrs; - Layouts.Layout.(line i ppf "%a\n" format (of_sort l)); + line i ppf "%a\n" Layouts.Sort.format l; expression i ppf e; | Tstr_value (rf, l) -> line i ppf "Tstr_value %a\n" fmt_rec_flag rf; diff --git a/ocaml/typing/subst.ml b/ocaml/typing/subst.ml index 28ced7d11d3..4bf9f1fd551 100644 --- a/ocaml/typing/subst.ml +++ b/ocaml/typing/subst.ml @@ -31,7 +31,11 @@ type t = { types: type_replacement Path.Map.t; modules: Path.t Path.Map.t; modtypes: module_type Path.Map.t; - for_saving: bool; + + (* given function should be applied to all layouts when saving; this commons + them up and truncates their histories *) + for_saving: (layout -> layout) option; + loc: Location.t option; mutable last_compose: (t * t) option (* Memoized composition *) } @@ -39,7 +43,7 @@ let identity = { types = Path.Map.empty; modules = Path.Map.empty; modtypes = Path.Map.empty; - for_saving = false; + for_saving = None; loc = None; last_compose = None; } @@ -61,7 +65,34 @@ let add_modtype_path p ty s = { s with modtypes = Path.Map.add p ty s.modtypes; last_compose = None } let add_modtype id ty s = add_modtype_path (Pident id) ty s -let for_saving s = { s with for_saving = true; last_compose = None } +let for_saving s = + (* CR layouts: it would be better to put all this stuff outside this + function, but it's in here because we really want to tailor the reason + to describe the module a symbol is imported from. But RAE's initial + attempt to do this based on filename caused spurious "inconsistent + assumption" errors that couldn't immediately be solved. Revisit + with a better approach. *) + let reason = Layout.Imported in + let any = Layout.of_const Any ~why:reason in + let void = Layout.of_const Void ~why:reason in + let value = Layout.of_const Value ~why:reason in + let immediate = Layout.of_const Immediate ~why:reason in + let immediate64 = Layout.of_const Immediate64 ~why:reason in + let share_layout lay = + match Layout.get lay with + | Const Any -> any + | Const Void -> void + | Const Value -> value + | Const Immediate -> immediate + | Const Immediate64 -> immediate64 + | Var _ -> lay + in + { s with for_saving = Some share_layout; last_compose = None } + +let apply_share_layout s lay = + match s.for_saving with + | Some share_layout -> share_layout lay + | None -> lay let change_locs s loc = { s with loc = Some loc; last_compose = None } @@ -69,7 +100,8 @@ let loc s x = match s.loc with | Some l -> l | None -> - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if Option.is_some s.for_saving && not !Clflags.keep_locs + then Location.none else x let remove_loc = let open Ast_mapper in @@ -84,11 +116,11 @@ let is_not_doc = function let attrs s x = let x = - if s.for_saving && not !Clflags.keep_docs then + if Option.is_some s.for_saving && not !Clflags.keep_docs then List.filter is_not_doc x else x in - if s.for_saving && not !Clflags.keep_locs + if Option.is_some s.for_saving && not !Clflags.keep_locs then remove_loc.Ast_mapper.attributes remove_loc x else x @@ -150,51 +182,25 @@ let newpersty desc = create_expr desc ~level:generic_level ~scope:Btype.lowest_level ~id:!new_id -(* ensure that all occurrences of 'Tvar None' are physically shared when saving - artifacts *) -let tvar_none_any = Tvar { name = None; layout = Layout.any } -let tvar_none_imm = Tvar { name = None; layout = Layout.immediate } -let tvar_none_imm64 = Tvar { name = None; layout = Layout.immediate64 } -let tvar_none_val = Tvar { name = None; layout = Layout.value } -let tvar_none_void = Tvar { name = None; layout = Layout.void } - -let tunivar_none_any = Tunivar { name = None; layout = Layout.any } -let tunivar_none_imm = Tunivar { name = None; layout = Layout.immediate } -let tunivar_none_imm64 = Tunivar { name = None; layout = Layout.immediate64 } -let tunivar_none_val = Tunivar { name = None; layout = Layout.value } -let tunivar_none_void = Tunivar { name = None; layout = Layout.void} - -let norm = function - | (Tvar { name = None; layout }) as t -> begin - match Layout.get layout with - | Const Any -> tvar_none_any - | Const Immediate -> tvar_none_imm - | Const Immediate64 -> tvar_none_imm64 - | Const Value -> tvar_none_val - | Const Void -> tvar_none_void - | Var _ -> t - end - | (Tunivar { name = None; layout }) as t -> begin - match Layout.get layout with - | Const Any -> tunivar_none_any - | Const Immediate -> tunivar_none_imm - | Const Immediate64 -> tunivar_none_imm64 - | Const Value -> tunivar_none_val - | Const Void -> tunivar_none_void - | Var _ -> t - end - | d -> d +let norm s desc = match s with + | { for_saving = Some share_layout; _ } -> begin match desc with + | Tvar { name; layout } -> Tvar { name; layout = share_layout layout } + | Tunivar { name; layout } -> Tunivar { name; layout = share_layout layout } + | desc -> desc + end + | { for_saving = None; _ } -> assert false let ctype_apply_env_empty = ref (fun _ -> assert false) (* Similar to [Ctype.nondep_type_rec]. *) let rec typexp copy_scope s ty = + let for_saving = Option.is_some s.for_saving in let desc = get_desc ty in match desc with Tvar _ | Tunivar _ -> - if s.for_saving || get_id ty < 0 then + if for_saving || get_id ty < 0 then let ty' = - if s.for_saving then newpersty (norm desc) + if for_saving then newpersty (norm s desc) else newty2 ~level:(get_level ty) desc in For_copy.redirect_desc copy_scope ty (Tsubst (ty', None)); @@ -202,7 +208,7 @@ let rec typexp copy_scope s ty = else ty | Tsubst (ty, _) -> ty - | Tfield (m, k, _t1, _t2) when not s.for_saving && m = dummy_method + | Tfield (m, k, _t1, _t2) when not for_saving && m = dummy_method && field_kind_repr k <> Fabsent && get_level ty < generic_level -> (* do not copy the type of self when it is not generalized *) ty @@ -215,9 +221,9 @@ let rec typexp copy_scope s ty = let has_fixed_row = not (is_Tconstr ty) && is_constr_row ~allow_ident:false tm in (* Make a stub *) - let layout = Layout.any in + let layout = Layout.any ~why:Dummy_layout in let ty' = - if s.for_saving then newpersty (Tvar {name = None; layout}) + if for_saving then newpersty (Tvar {name = None; layout}) else newgenstub ~scope:(get_scope ty) layout in For_copy.redirect_desc copy_scope ty (Tsubst (ty', None)); @@ -264,7 +270,7 @@ let rec typexp copy_scope s ty = Tlink ty2 | _ -> let dup = - s.for_saving || get_level more = generic_level || + for_saving || get_level more = generic_level || static_row row || is_Tconstr more in (* Various cases for the row variable *) let more' = @@ -272,7 +278,7 @@ let rec typexp copy_scope s ty = Tsubst (ty, None) -> ty | Tconstr _ | Tnil -> typexp copy_scope s more | Tunivar _ | Tvar _ -> - if s.for_saving then newpersty (norm mored) + if for_saving then newpersty mored else if dup && is_Tvar more then newgenty mored else more | _ -> assert false @@ -313,7 +319,7 @@ let label_declaration copy_scope s l = ld_id = l.ld_id; ld_mutable = l.ld_mutable; ld_global = l.ld_global; - ld_layout = l.ld_layout; + ld_layout = apply_share_layout s l.ld_layout; ld_type = typexp copy_scope s l.ld_type; ld_loc = loc s l.ld_loc; ld_attributes = attrs s l.ld_attributes; @@ -336,16 +342,49 @@ let constructor_declaration copy_scope s c = cd_uid = c.cd_uid; } +(* called only when for_saving is set *) +let constructor_tag share_layout = function + | Ordinary _ as tag -> tag + | Extension (path, lays) -> Extension (path, Array.map share_layout lays) + +(* called only when for_saving is set *) +let variant_representation share_layout = function + | Variant_unboxed -> Variant_unboxed + | Variant_boxed layss -> + Variant_boxed (Array.map (Array.map share_layout) layss) + | Variant_extensible -> Variant_extensible + +(* called only when for_saving is set *) +let record_representation share_layout = function + | Record_unboxed -> Record_unboxed + | Record_inlined (tag, variant_rep) -> + Record_inlined (constructor_tag share_layout tag, + variant_representation share_layout variant_rep) + | Record_boxed lays -> Record_boxed (Array.map share_layout lays) + | Record_float -> Record_float + let type_declaration' copy_scope s decl = + let share_layout, for_saving = match s.for_saving with + | Some share_layout -> share_layout, true + | None -> Fun.id, false + in { type_params = List.map (typexp copy_scope s) decl.type_params; type_arity = decl.type_arity; type_kind = begin match decl.type_kind with Type_abstract -> Type_abstract | Type_variant (cstrs, rep) -> + let rep = if for_saving + then variant_representation share_layout rep + else rep + in Type_variant (List.map (constructor_declaration copy_scope s) cstrs, rep) | Type_record(lbls, rep) -> + let rep = if for_saving + then record_representation share_layout rep + else rep + in Type_record (List.map (label_declaration copy_scope s) lbls, rep) | Type_open -> Type_open end; @@ -355,7 +394,7 @@ let type_declaration' copy_scope s decl = None -> None | Some ty -> Some(typexp copy_scope s ty) end; - type_layout = decl.type_layout; + type_layout = share_layout decl.type_layout; type_private = decl.type_private; type_variance = decl.type_variance; type_separability = decl.type_separability; @@ -433,12 +472,16 @@ let extension_constructor' copy_scope s ext = { ext_type_path = type_path s ext.ext_type_path; ext_type_params = List.map (typexp copy_scope s) ext.ext_type_params; ext_args = constructor_arguments copy_scope s ext.ext_args; - ext_arg_layouts = ext.ext_arg_layouts; + ext_arg_layouts = begin match s.for_saving with + | Some share_layouts -> Array.map share_layouts ext.ext_arg_layouts + | None -> ext.ext_arg_layouts + end; ext_constant = ext.ext_constant; ext_ret_type = Option.map (typexp copy_scope s) ext.ext_ret_type; ext_private = ext.ext_private; ext_attributes = attrs s ext.ext_attributes; - ext_loc = if s.for_saving then Location.none else ext.ext_loc; + ext_loc = if Option.is_some s.for_saving + then Location.none else ext.ext_loc; ext_uid = ext.ext_uid; } @@ -686,7 +729,9 @@ and compose s1 s2 = { types = merge_path_maps (type_replacement s2) s1.types s2.types; modules = merge_path_maps (module_path s2) s1.modules s2.modules; modtypes = merge_path_maps (modtype Keep s2) s1.modtypes s2.modtypes; - for_saving = s1.for_saving || s2.for_saving; + for_saving = Misc.Stdlib.Option.first_some + s1.for_saving + (fun () -> s2.for_saving); loc = keep_latest_loc s1.loc s2.loc; last_compose = None } diff --git a/ocaml/typing/typeclass.ml b/ocaml/typing/typeclass.ml index 7132a8111ce..d6f96ec8a13 100644 --- a/ocaml/typing/typeclass.ml +++ b/ocaml/typing/typeclass.ml @@ -109,7 +109,7 @@ type error = | Duplicate of string * string | Closing_self_type of class_signature | Polymorphic_class_parameter - | Non_value_binding of string * Layout.Violation.violation + | Non_value_binding of string * Layout.Violation.t exception Error of Location.t * Env.t * error exception Error_forward of Location.error @@ -306,8 +306,8 @@ let rec class_type_field env sign self_scope ctf = let cty = transl_simple_type env ~closed:false Global sty in let ty = cty.ctyp_type in begin match - Ctype.constrain_type_layout ~reason:(Fixed_layout Instance_variable) - env ty Layout.value + Ctype.constrain_type_layout + env ty (Layout.value ~why:Instance_variable) with | Ok _ -> () | Error err -> raise (Error(loc, env, Non_value_binding(lab, err))) @@ -321,7 +321,9 @@ let rec class_type_field env sign self_scope ctf = let sty = Ast_helper.Typ.force_poly sty in match sty.ptyp_desc, priv with | Ptyp_poly ([],sty'), Public -> - let expected_ty = Ctype.newvar Layout.value in + let expected_ty = + Ctype.newvar (Layout.value ~why:Object_field) + in add_method loc env lab priv virt expected_ty sign; let returned_cty = ctyp Ttyp_any (Ctype.newty Tnil) env loc in delayed_meth_specs := @@ -668,8 +670,8 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf = end; begin match - Ctype.constrain_type_layout ~reason:(Fixed_layout Class_field) - val_env ty Layout.value + Ctype.constrain_type_layout + val_env ty (Layout.value ~why:Class_field) with | Ok _ -> () | Error err -> raise (Error(label.loc, val_env, @@ -717,8 +719,9 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf = end; begin match - Ctype.constrain_type_layout ~reason:(Fixed_layout Class_field) - val_env definition.exp_type Layout.value + Ctype.constrain_type_layout + val_env definition.exp_type + (Layout.value ~why:Class_field) with | Ok _ -> () | Error err -> raise (Error(label.loc, val_env, @@ -788,7 +791,7 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf = in let ty = match sty with - | None -> Ctype.newvar Layout.value + | None -> Ctype.newvar (Layout.value ~why:Object_field) | Some sty -> let sty = Ast_helper.Typ.force_poly sty in let cty' = @@ -801,7 +804,9 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf = try match get_desc ty with | Tvar _ -> - let ty' = Ctype.newvar Layout.value in + let ty' = + Ctype.newvar (Layout.value ~why:Object_field) + in Ctype.unify val_env (Ctype.newmono ty') ty; type_approx val_env sbody ty' | Tpoly (ty1, tl) -> @@ -1360,11 +1365,13 @@ and class_expr_aux cl_num val_env met_env virt self_scope scl = List.iter (fun (loc, mode, sort) -> Typecore.escape ~loc ~env:val_env ~reason:Other mode; - match Layout.sub (Layout.of_sort sort) Layout.value with - | Ok () -> () - | Error err -> - raise (Error(loc,met_env, - Non_value_binding (Ident.name id,err))) + if not (Sort.equate sort Sort.value) + then let viol = Layout.Violation.of_ (Not_a_sublayout( + Layout.of_sort ~why:Let_binding sort, + Layout.value ~why:Class_let_binding)) + in + raise (Error(loc, met_env, + Non_value_binding (Ident.name id, viol))) ) modes_and_sorts; let path = Pident id in @@ -1464,15 +1471,17 @@ and class_expr_aux cl_num val_env met_env virt self_scope scl = (* Approximate the type of the constructor to allow recursive use *) (* of optional parameters *) -let var_option = Predef.type_option (Btype.newgenvar Layout.value) +let var_option = + Predef.type_option (Btype.newgenvar (Layout.value ~why:Type_argument)) let rec approx_declaration cl = match cl.pcl_desc with Pcl_fun (l, _, _, cl) -> let arg = if Btype.is_optional l then Ctype.instance var_option - else Ctype.newvar Layout.value - (* CR layouts v2: use of value here may be relaxed *) + else Ctype.newvar (Layout.value ~why:Class_argument) + (* CR layouts: use of value here may be relaxed when we update + classes to work with layouts *) in let arg = Ctype.newmono arg in let arrow_desc = l, Alloc_mode.global, Alloc_mode.global in @@ -1482,36 +1491,37 @@ let rec approx_declaration cl = approx_declaration cl | Pcl_constraint (cl, _) -> approx_declaration cl - | _ -> Ctype.newvar Layout.value + | _ -> Ctype.newvar (Layout.value ~why:Object) let rec approx_description ct = match ct.pcty_desc with Pcty_arrow (l, _, ct) -> let arg = if Btype.is_optional l then Ctype.instance var_option - else Ctype.newvar Layout.value - (* CR layouts v2: use of value here may be relaxed *) + else Ctype.newvar (Layout.value ~why:Class_argument) + (* CR layouts: use of value here may be relaxed when we + relax layouts in classes *) in let arg = Ctype.newmono arg in let arrow_desc = l, Alloc_mode.global, Alloc_mode.global in Ctype.newty (Tarrow (arrow_desc, arg, approx_description ct, commu_ok)) - | _ -> Ctype.newvar Layout.value + | _ -> Ctype.newvar (Layout.value ~why:Object) (*******************************) let temp_abbrev loc env id arity uid = let params = ref [] in for _i = 1 to arity do - params := Ctype.newvar Layout.value :: !params + params := Ctype.newvar (Layout.value ~why:Type_argument) :: !params done; - let ty = Ctype.newobj (Ctype.newvar Layout.value) in + let ty = Ctype.newobj (Ctype.newvar (Layout.value ~why:Object)) in let env = Env.add_type ~check:true id {type_params = !params; type_arity = arity; type_kind = Type_abstract; - type_layout = Layout.value; + type_layout = Layout.value ~why:Object; type_private = Public; type_manifest = Some ty; type_variance = Variance.unknown_signature ~injective:false ~arity; @@ -1594,7 +1604,7 @@ let class_infos define_class kind let ci_params = let make_param (sty, v) = try - (transl_type_param env sty Layout.value, v) + (transl_type_param env sty (Layout.value ~why:Class_argument), v) with Already_bound -> raise(Error(sty.ptyp_loc, env, Repeated_parameter)) in @@ -1746,7 +1756,7 @@ let class_infos define_class kind type_params = obj_params; type_arity = arity; type_kind = Type_abstract; - type_layout = Layout.value; + type_layout = Layout.value ~why:Object; type_private = Public; type_manifest = Some obj_ty; type_variance = Variance.unknown_signature ~injective:false ~arity; @@ -1769,7 +1779,7 @@ let class_infos define_class kind type_params = cl_params; type_arity = arity; type_kind = Type_abstract; - type_layout = Layout.value; + type_layout = Layout.value ~why:Object; type_private = Public; type_manifest = Some cl_ty; type_variance = Variance.unknown_signature ~injective:false ~arity; diff --git a/ocaml/typing/typeclass.mli b/ocaml/typing/typeclass.mli index 355c5fdaf2a..4160099af85 100644 --- a/ocaml/typing/typeclass.mli +++ b/ocaml/typing/typeclass.mli @@ -125,7 +125,7 @@ type error = | Duplicate of string * string | Closing_self_type of class_signature | Polymorphic_class_parameter - | Non_value_binding of string * Layout.Violation.violation + | Non_value_binding of string * Layout.Violation.t exception Error of Location.t * Env.t * error exception Error_forward of Location.error diff --git a/ocaml/typing/typecore.ml b/ocaml/typing/typecore.ml index fba4e353cac..f63f0226e3c 100644 --- a/ocaml/typing/typecore.ml +++ b/ocaml/typing/typecore.ml @@ -121,7 +121,7 @@ type error = Datatype_kind.t * Longident.t * (Path.t * Path.t) * (Path.t * Path.t) list | Invalid_format of string | Not_an_object of type_expr * type_forcing_context option - | Not_a_value of Layout.Violation.violation * type_forcing_context option + | Not_a_value of Layout.Violation.t * type_forcing_context option | Undefined_method of type_expr * string * string list option | Undefined_self_method of string * string list | Virtual_class of Longident.t @@ -916,7 +916,7 @@ let enter_orpat_variables loc env p1_vs p2_vs = pv1 :: vars, alist else begin begin try - unify_var env (newvar Layout.any) t1; + unify_var env (newvar (Layout.any ~why:Dummy_layout)) t1; unify env t1 t2 with | Unify err -> @@ -996,7 +996,8 @@ and build_as_type_aux ~refine ~mode (env : Env.t ref) p = in let ty = let fields = [l, rf_present ty] in - newty (Tvariant (create_row ~fields ~more:(newvar Layout.value) + newty (Tvariant (create_row ~fields + ~more:(newvar (Layout.value ~why:Row_variable)) ~name:None ~fixed:None ~closed:false)) in ty, mode @@ -1007,7 +1008,7 @@ and build_as_type_aux ~refine ~mode (env : Env.t ref) p = [unify_pat]. *) (* CR layouts v2: This should be a sort variable and could be now (but think about when it gets defaulted.) *) - let ty = newvar Layout.any in + let ty = newvar (Layout.any ~why:Dummy_layout) in let ppl = List.map (fun (_, l, p) -> l.lbl_num, p) lpl in let do_label lbl = let _, ty_arg, ty_res = instance_label false lbl in @@ -1048,7 +1049,9 @@ and build_as_type_aux ~refine ~mode (env : Env.t ref) p = in let ty = newty (Tvariant (create_row ~fields ~fixed ~name - ~closed:false ~more:(newvar Layout.value))) + ~closed:false + ~more:(newvar + (Layout.value ~why:Row_variable)))) in ty, mode end @@ -1084,7 +1087,8 @@ let solve_Ppat_tuple (type a) ~refine ~alloc_mode loc env (args : a list) expect let ann = (* CR layouts v5: restriction to value here to be relaxed. *) List.map2 - (fun p mode -> (p, newgenvar Layout.value, simple_pat_mode mode)) + (fun p mode -> (p, newgenvar (Layout.value ~why:Tuple_element), + simple_pat_mode mode)) args arg_modes in let ty = newgenty (Ttuple (List.map snd3 ann)) in @@ -1100,7 +1104,8 @@ let solve_constructor_annotation tps env name_list sty ty_args ty_ex = (* CR layouts v1.5: I expect this needs to change when we allow layout annotations on explicitly quantified vars in gadt constructors. See: https://github.com/ocaml/ocaml/pull/9584/ *) - let decl = new_local_type ~loc:name.loc Layout.value in + let decl = new_local_type ~loc:name.loc + (Layout.value ~why:Existential_type_variable) in let (id, new_env) = Env.enter_type ~scope:expansion_scope name.txt decl !env in env := new_env; @@ -1230,14 +1235,14 @@ let solve_Ppat_array ~refine loc env mutability expected_ty = | Mutable -> Predef.type_array in (* CR layouts v4: in the future we'll have arrays of other layouts *) - let ty_elt = newgenvar Layout.value in + let ty_elt = newgenvar (Layout.value ~why:Array_element) in let expected_ty = generic_instance expected_ty in unify_pat_types ~refine loc env (type_some_array ty_elt) expected_ty; ty_elt let solve_Ppat_lazy ~refine loc env expected_ty = - let nv = newgenvar Layout.value in + let nv = newgenvar (Layout.value ~why:Lazy_expression) in unify_pat_types ~refine loc env (Predef.type_lazy_t nv) (generic_instance expected_ty); nv @@ -1260,23 +1265,32 @@ let solve_Ppat_constraint ~refine tps loc env mode sty expected_ty = let solve_Ppat_variant ~refine loc env tag no_arg expected_ty = (* CR layouts v5: relax the restriction to value here. *) - let arg_type = if no_arg then [] else [newgenvar Layout.value] in + let arg_type = + if no_arg + then [] + else [newgenvar (Layout.value ~why:Polymorphic_variant_field)] + in let fields = [tag, rf_either ~no_arg arg_type ~matched:true] in let make_row more = create_row ~fields ~closed:false ~more ~fixed:None ~name:None in - let row = make_row (newgenvar Layout.value) in + let row = make_row (newgenvar (Layout.value ~why:Row_variable)) in let expected_ty = generic_instance expected_ty in (* PR#7404: allow some_private_tag blindly, as it would not unify with the abstract row variable *) if tag <> Parmatch.some_private_tag then unify_pat_types ~refine loc env (newgenty(Tvariant row)) expected_ty; - (arg_type, make_row (newvar Layout.value), instance expected_ty) + (arg_type, make_row (newvar (Layout.value ~why:Row_variable)), + instance expected_ty) (* Building the or-pattern corresponding to a polymorphic variant type *) let build_or_pat env loc lid = let path, decl = Env.lookup_type ~loc:lid.loc lid.txt env in - let tyl = List.map (fun _ -> newvar Layout.value) decl.type_params in + (* CR layouts: the use of value here is wrong: + there could be other layouts in a polymorphic variant argument; + see Test 24 in tests/typing-layouts/basics_alpha.ml *) + let tyl = List.map (fun _ -> newvar (Layout.value ~why:Type_argument)) + decl.type_params in let row0 = let ty = expand_head env (newty(Tconstr(path, tyl, ref Mnil))) in match get_desc ty with @@ -1304,9 +1318,12 @@ let build_or_pat env loc lid = let name = Some (path, tyl) in let make_row more = create_row ~fields ~more ~closed:false ~fixed:None ~name in - let ty = newty (Tvariant (make_row (newvar Layout.value))) in + let ty = newty (Tvariant (make_row + (newvar + (Layout.value ~why:Row_variable)))) + in let gloc = Location.ghostify loc in - let row' = ref (make_row (newvar Layout.value)) in + let row' = ref (make_row (newvar (Layout.value ~why:Row_variable))) in let pats = List.map (fun (l,p) -> @@ -2467,7 +2484,8 @@ and type_pat_aux | Record_type(p0, p, _, _) -> let ty = generic_instance expected_ty in Some (p0, p, is_principal expected_ty), ty - | Maybe_a_record_type -> None, newvar Layout.value + | Maybe_a_record_type -> + None, newvar (Layout.value ~why:Boxed_record) | Not_a_record_type -> let error = Wrong_expected_kind(Record, Pattern, expected_ty) in raise (Error (loc, !env, error)) @@ -2754,7 +2772,7 @@ let type_class_arg_pattern cl_num val_env met_env l spat = if !Clflags.principal then Ctype.begin_def (); let tps = create_type_pat_state Modules_rejected in (* CR layouts: will change when we relax layout restrictions in classes. *) - let nv = newvar Layout.value in + let nv = newvar (Layout.value ~why:Class_argument) in let alloc_mode = simple_pat_mode Value_mode.global in let pat = type_pat tps Value ~no_existentials:In_class_args ~alloc_mode @@ -2766,7 +2784,8 @@ let type_class_arg_pattern cl_num val_env met_env l spat = List.iter (fun f -> f()) tps.tps_pattern_force; (* CR layouts v5: value restriction here to be relaxed *) if is_optional l then - unify_pat (ref val_env) pat (type_option (newvar Layout.value)); + unify_pat (ref val_env) pat + (type_option (newvar (Layout.value ~why:Type_argument))); let pvs = tps.tps_pattern_variables in if !Clflags.principal then begin Ctype.end_def (); @@ -2810,7 +2829,7 @@ let type_self_pattern env spat = let open Ast_helper in let spat = Pat.mk(Ppat_alias (spat, mknoloc "selfpat-*")) in let tps = create_type_pat_state Modules_rejected in - let nv = newvar Layout.value in + let nv = newvar (Layout.value ~why:Object) in let alloc_mode = simple_pat_mode Value_mode.global in let pat = type_pat tps Value ~no_existentials:In_self_pattern ~alloc_mode @@ -3040,9 +3059,13 @@ let collect_unknown_apply_args env funct ty_fun mode_fun rev_args sargs ret_tvar let ty_fun = expand_head env ty_fun in match get_desc ty_fun with | Tvar _ -> - let ty_arg_mono = newvar (Layout.of_new_sort_var ()) in + let ty_arg_mono = + newvar (Layout.of_new_sort_var ~why:Function_argument) + in let ty_arg = newmono ty_arg_mono in - let ty_res = newvar (Layout.of_new_sort_var ()) in + let ty_res = + newvar (Layout.of_new_sort_var ~why:Function_result) + in if ret_tvar && not (is_prim ~name:"%identity" funct) && not (is_prim ~name:"%obj_magic" funct) @@ -3465,7 +3488,7 @@ let rec approx_type env sty = match sty.ptyp_desc with | Ptyp_arrow (p, ({ ptyp_desc = Ptyp_poly _ } as arg_sty), sty) -> (* CR layouts v5: value requirement here to be relaxed *) - if is_optional p then newvar Layout.value + if is_optional p then newvar (Layout.value ~why:Type_argument) else begin let arg_mode = Typetexp.get_alloc_mode arg_sty in let arg_ty = @@ -3483,8 +3506,8 @@ let rec approx_type env sty = let arg_mode = Typetexp.get_alloc_mode arg_sty in let arg = if is_optional p - then type_option (newvar Layout.value) - else newvar (Layout.of_new_sort_var ()) + then type_option (newvar (Layout.value ~why:Type_argument)) + else newvar (Layout.of_new_sort_var ~why:Function_argument) in let ret = approx_type env sty in let marg = Alloc_mode.of_const arg_mode in @@ -3494,7 +3517,8 @@ let rec approx_type env sty = newty (Ttuple (List.map (approx_type env) args)) | Ptyp_constr (lid, ctl) -> let path, decl = Env.lookup_type ~use:false ~loc:lid.loc lid.txt env in - if List.length ctl <> decl.type_arity then newvar Layout.any + if List.length ctl <> decl.type_arity + then newvar (Layout.any ~why:Dummy_layout) else begin let tyl = List.map (approx_type env) ctl in newconstr path tyl @@ -3503,7 +3527,7 @@ let rec approx_type env sty = that could be matched on and have anys in them. But once we do, this should probably be sort variable. See Test21 in typing-layouts/basics.ml (which mentions approx_type) for why it can't be value. *) - | _ -> newvar Layout.any + | _ -> newvar (Layout.any ~why:Dummy_layout) and approx_type_jst _env _attrs : Jane_syntax.Core_type.t -> _ = function | _ -> . @@ -3587,7 +3611,9 @@ and type_approx_aux env sexp in_function ty_expected = | Pexp_match (_, {pc_rhs=e}::_) -> type_approx_aux env e None ty_expected | Pexp_try (e, _) -> type_approx_aux env e None ty_expected | Pexp_tuple l -> - let tys = List.map (fun _ -> newvar Layout.value) l in + let tys = List.map + (fun _ -> newvar (Layout.value ~why:Tuple_element)) l + in let ty = newty (Ttuple tys) in begin try unify env ty ty_expected with Unify err -> raise(Error(sexp.pexp_loc, env, Expr_type_clash (err, None, None))) @@ -3670,11 +3696,8 @@ let check_univars env kind exp ty_expected vars = 2) [polyfy] actually calls [expand_head] twice! why?! *) match get_desc (expand_head env var) with - | Tvar { name; layout = layout2; } -> begin - match - check_type_layout ~reason:(Unified_with_tvar name) - env uvar layout2 - with + | Tvar { layout = layout2; } -> begin + match check_type_layout env uvar layout2 with | Ok _ -> () | Error err -> error exp_ty ty_expected @@ -3924,7 +3947,8 @@ let check_absent_variant env = let fields = [s, rf_either ty_arg ~no_arg:(arg=None) ~matched:true] in let row' = create_row ~fields - ~more:(newvar Layout.value) ~closed:false ~fixed:None ~name:None + ~more:(newvar (Layout.value ~why:Row_variable)) + ~closed:false ~fixed:None ~name:None in (* Should fail *) unify_pat (ref env) {pat with pat_type = newty (Tvariant row')} @@ -4033,7 +4057,8 @@ let with_explanation explanation f = let rec type_exp ?recarg env expected_mode sexp = (* We now delegate everything to type_expect *) - type_expect ?recarg env expected_mode sexp (mk_expected (newvar Layout.any)) + type_expect ?recarg env expected_mode sexp + (mk_expected (newvar (Layout.any ~why:Dummy_layout))) (* Typing of an expression with an expected type. This provide better error messages, and allows controlled @@ -4208,7 +4233,9 @@ and type_expect_ let bound_exp = vb.vb_expr in let bound_exp_type = Ctype.instance bound_exp.exp_type in let loc = proper_exp_loc bound_exp in - let outer_var = newvar2 outer_level Layout.any in + let outer_var = + newvar2 outer_level (Layout.any ~why:Dummy_layout) + in (* Checking unification within an environment extended with the module bindings allows us to correctly accept more programs. This environment allows unification to identify more cases where @@ -4220,7 +4247,7 @@ and type_expect_ if may_contain_modules then begin end_def (); (* The "body" component of the scope escape check. *) - unify_exp new_env body (newvar Layout.any); + unify_exp new_env body (newvar (Layout.any ~why:Dummy_layout)); end; re { exp_desc = Texp_let(rec_flag, pat_exp_list, body); @@ -4367,16 +4394,17 @@ and type_expect_ if TypeSet.mem ty seen then false else match get_desc ty with Tarrow (_l, ty_arg, ty_fun, _com) -> - (try unify_var env (newvar Layout.any) ty_arg + (try unify_var env + (newvar (Layout.any ~why:Dummy_layout)) ty_arg with Unify _ -> assert false); ret_tvar (TypeSet.add ty seen) ty_fun | Tvar _ -> - let v = newvar Layout.any in + let v = newvar (Layout.any ~why:Dummy_layout) in let rt = get_level ty > get_level v in unify_var env v ty; rt | _ -> - let v = newvar Layout.any in + let v = newvar (Layout.any ~why:Dummy_layout) in unify_var env v ty; false in @@ -4443,7 +4471,7 @@ and type_expect_ let sort = Sort.new_var () in let arg = type_expect env arg_expected_mode sarg - (mk_expected (newvar (Layout.of_sort sort))) + (mk_expected (newvar (Layout.of_sort ~why:Match sort))) in end_def (); if maybe_expansive arg then lower_contravariant env arg.exp_type; @@ -4477,7 +4505,10 @@ and type_expect_ assert (arity >= 2); let alloc_mode = register_allocation expected_mode in (* CR layouts v5: non-values in tuples *) - let subtypes = List.map (fun _ -> newgenvar Layout.value) sexpl in + let subtypes = + List.map (fun _ -> newgenvar (Layout.value ~why:Tuple_element)) + sexpl + in let to_unify = newgenty (Ttuple subtypes) in with_explanation (fun () -> unify_exp_types loc env to_unify (generic_instance ty_expected)); @@ -4545,7 +4576,7 @@ and type_expect_ let row = create_row ~fields: [l, rf_present arg_type] - ~more: (newvar Layout.value) + ~more: (newvar (Layout.value ~why:Row_variable)) ~closed: false ~fixed: None ~name: None @@ -4595,7 +4626,8 @@ and type_expect_ raise (Error (exp.exp_loc, env, error)) in match expected_opath, opt_exp_opath with - | None, None -> newvar (Layout.of_new_sort_var ()), None + | None, None -> + newvar (Layout.of_new_sort_var ~why:Record_projection), None | Some _, None -> ty_expected, expected_opath | Some(_, _, true), Some _ -> ty_expected, expected_opath | (None | Some (_, _, false)), Some (_, p', _) -> @@ -4755,7 +4787,8 @@ and type_expect_ let (record, rmode, label, expected_type) = type_label_access env srecord Env.Mutation lid in let ty_record = - if expected_type = None then newvar (Layout.of_new_sort_var ()) + if expected_type = None + then newvar (Layout.of_new_sort_var ~why:Record_assignment) else record.exp_type in let (label_loc, label, newval) = @@ -4911,7 +4944,7 @@ and type_expect_ begin_def (); let arg = type_exp env expected_mode sarg in end_def (); - let tv = newvar Layout.any in + let tv = newvar (Layout.any ~why:Dummy_layout) in let gen = generalizable (get_level tv) arg.exp_type in unify_var env tv arg.exp_type; begin match arg.exp_desc, !self_coercion, get_desc ty' with @@ -5005,7 +5038,7 @@ and type_expect_ | id -> id, Btype.method_type met sign | exception Not_found -> let id = Ident.create_local met in - let ty = newvar Layout.value in + let ty = newvar (Layout.value ~why:Object_field) in meths_ref := Meths.add met id !meths_ref; add_method env met Private Virtual ty sign; Location.prerr_warning loc @@ -5076,7 +5109,7 @@ and type_expect_ (Warnings.Not_principal "this use of a polymorphic method"); snd (instance_poly false tl ty) | Tvar _ -> - let ty' = newvar Layout.value in + let ty' = newvar (Layout.value ~why:Object_field) in unify env (instance typ) (newty(Tpoly(ty',[]))); (* if not !Clflags.nolabels then Location.prerr_warning loc (Warnings.Unknown_method met); *) @@ -5171,7 +5204,7 @@ and type_expect_ assert false end | Pexp_letmodule(name, smodl, sbody) -> - let ty = newvar Layout.any in + let ty = newvar (Layout.any ~why:Dummy_layout) in (* remember original level *) begin_def (); let modl, pres, id, new_env = Typetexp.TyVarEnv.with_local_scope begin fun () -> @@ -5246,7 +5279,7 @@ and type_expect_ exp_env = env; } | Pexp_lazy e -> - let ty = newgenvar Layout.value in + let ty = newgenvar (Layout.value ~why:Lazy_expression) in let to_unify = Predef.type_lazy_t ty in with_explanation (fun () -> unify_exp_types loc env to_unify (generic_instance ty_expected)); @@ -5311,15 +5344,15 @@ and type_expect_ in re { exp with exp_extra = (Texp_poly cty, loc, sexp.pexp_attributes) :: exp.exp_extra } - | Pexp_newtype({txt=name} as lname, sbody) -> + | Pexp_newtype({txt=name}, sbody) -> let layout = match Layout.of_attributes_default ~legacy_immediate:false - ~reason:(Newtype_declaration lname) - ~default:Layout.value sexp.pexp_attributes + ~reason:(Newtype_declaration name) + ~default:(Layout.value ~why:Univar) sexp.pexp_attributes with | Ok l -> l - | Error (loc, layout) -> - raise (Error (loc, env, Layout_not_enabled layout)) + | Error { loc; txt } -> + raise (Error (loc, env, Layout_not_enabled txt)) in let ty = if Typetexp.valid_tyvar_name name then @@ -5383,7 +5416,7 @@ and type_expect_ exp_attributes = sexp.pexp_attributes; exp_env = env } | Pexp_open (od, e) -> - let tv = newvar Layout.any in + let tv = newvar (Layout.any ~why:Dummy_layout) in let (od, _, newenv) = !type_open_decl env od in let exp = type_expect newenv expected_mode e ty_expected_explained in (* Force the return type to be well-formed in the original @@ -5403,7 +5436,7 @@ and type_expect_ | [] -> spat_acc, ty_acc | { pbop_pat = spat; _} :: rest -> (* CR layouts v5: eliminate value requirement *) - let ty = newvar Layout.value in + let ty = newvar (Layout.value ~why:Tuple_element) in let loc = Location.ghostify slet.pbop_op.loc in let spat_acc = Ast_helper.Pat.tuple ~loc [spat_acc; spat] in let ty_acc = newty (Ttuple [ty_acc; ty]) in @@ -5414,24 +5447,22 @@ and type_expect_ let op_path, op_desc = type_binding_op_ident env slet.pbop_op in let op_type = instance op_desc.val_type in let spat_params, ty_params = - (* The use of a sort var here instead of a value is a little suspect, - because this can be the component of a tuple if there are several - [and] operators. In practice, all will be OK, though, because this - type will get unified with a tuple type (in the [type_cases] below) - and the sort var will get set to [value]. However, we still use a - sort var here to allow for a non-[value] type when there are no - [and]s. *) - (* CR layouts v5: Remove above comment when we support tuples of - non-[value] types. *) - loop slet.pbop_pat (newvar (Layout.of_new_sort_var ())) sands - in - let ty_func_result = newvar (Layout.of_new_sort_var ()) in + let initial_layout = match sands with + | [] -> Layout.of_new_sort_var ~why:Function_argument + (* CR layouts v5: eliminate value requirement for tuple elements *) + | _ -> Layout.value ~why:Tuple_element + in + loop slet.pbop_pat (newvar initial_layout) sands + in + let ty_func_result = + newvar (Layout.of_new_sort_var ~why:Function_result) + in let arrow_desc = Nolabel, Alloc_mode.global, Alloc_mode.global in let ty_func = newty (Tarrow(arrow_desc, newmono ty_params, ty_func_result, commu_ok)) in - let ty_result = newvar (Layout.of_new_sort_var ()) in - let ty_andops = newvar (Layout.of_new_sort_var ()) in + let ty_result = newvar (Layout.of_new_sort_var ~why:Function_result) in + let ty_andops = newvar (Layout.of_new_sort_var ~why:Function_argument) in let ty_op = newty (Tarrow(arrow_desc, newmono ty_andops, newty (Tarrow(arrow_desc, newmono ty_func, @@ -5695,7 +5726,7 @@ and type_function ?in_function loc attrs env (expected_mode : expected_mode) let snap = Btype.snapshot () in let really_poly = try - unify env (newmono (newvar Layout.any)) ty_arg; + unify env (newmono (newvar (Layout.any ~why:Dummy_layout))) ty_arg; false with Unify _ -> true in @@ -6334,7 +6365,8 @@ and type_apply_arg env ~app_loc ~funct ~index ~position ~partial_app (lbl, arg) in if is_optional lbl then (* CR layouts v5: relax value requirement *) - unify_exp env arg (type_option(newvar Layout.value)); + unify_exp env arg + (type_option(newvar (Layout.value ~why:Type_argument))); (lbl, Arg (arg, expected_mode.mode)) | Arg (Known_arg { sarg; ty_arg; ty_arg0; mode_arg; wrapped_in_some }) -> @@ -6360,7 +6392,8 @@ and type_apply_arg env ~app_loc ~funct ~index ~position ~partial_app (lbl, arg) let snap = Btype.snapshot () in let really_poly = try - unify env (newmono (newvar Layout.any)) ty_arg; + unify env (newmono (newvar (Layout.any ~why:Dummy_layout))) + ty_arg; false with Unify _ -> true in @@ -6586,7 +6619,8 @@ and type_statement ?explanation ?(position=RNontail) env sexp = let exp = type_exp env (mode_local_with_position position) sexp in end_def(); let ty = expand_head env exp.exp_type - and tv = newvar Layout.any in + and tv = newvar (Layout.any ~why:Dummy_layout) + in if is_Tvar ty && get_level ty > get_level tv then Location.prerr_warning (final_subexpression exp).exp_loc @@ -6692,7 +6726,7 @@ and type_cases else ty_res, (fun env -> env) in (* Unify all cases (delayed to keep it order-free) *) - let ty_arg' = newvar Layout.any in + let ty_arg' = newvar (Layout.any ~why:Dummy_layout) in let unify_pats ty = List.iter (fun { typed_pat = pat; pat_type_for_unif = pat_ty; _ } -> unify_pat_types pat.pat_loc (ref env) pat_ty ty @@ -6711,7 +6745,7 @@ and type_cases if take_partial_instance <> None then unify_pats (instance ty_arg); List.iter (fun { pat_vars; _ } -> iter_pattern_variables_type - (fun t -> unify_var env (newvar Layout.any) t) + (fun t -> unify_var env (newvar (Layout.any ~why:Dummy_layout)) t) pat_vars ) half_typed_cases; end_def (); @@ -6812,7 +6846,8 @@ and type_cases if create_inner_level then begin end_def (); (* Ensure that existential types do not escape *) - unify_exp_types loc env (instance ty_res) (newvar Layout.any); + unify_exp_types loc env (instance ty_res) + (newvar (Layout.any ~why:Dummy_layout)); end; cases, partial @@ -6902,7 +6937,9 @@ and type_let spat_sexp_list in let is_recursive = (rec_flag = Recursive) in let sorts = List.map (fun _ -> Sort.new_var ()) spatl in - let nvs = List.map (fun s -> newvar (Layout.of_sort s)) sorts in + let nvs = + List.map (fun s -> newvar (Layout.of_sort ~why:Let_binding s)) sorts + in if is_recursive then begin_def (); let (pat_list, new_env, force, pvs, mvs) = type_pattern_list Value existential_context env spatl nvs allow_modules @@ -7161,9 +7198,9 @@ and type_andops env sarg sands expected_ty = if !Clflags.principal then begin_def (); let op_path, op_desc = type_binding_op_ident env sop in let op_type = op_desc.val_type in - let ty_arg = newvar (Layout.of_new_sort_var ()) in - let ty_rest = newvar (Layout.of_new_sort_var ()) in - let ty_result = newvar (Layout.of_new_sort_var ()) in + let ty_arg = newvar (Layout.of_new_sort_var ~why:Function_argument) in + let ty_rest = newvar (Layout.of_new_sort_var ~why:Function_argument) in + let ty_result = newvar (Layout.of_new_sort_var ~why:Function_result) in let arrow_desc = (Nolabel,Alloc_mode.global,Alloc_mode.global) in let ty_rest_fun = newty (Tarrow(arrow_desc, newmono ty_arg, ty_result, commu_ok)) @@ -7218,7 +7255,7 @@ and type_generic_array = let alloc_mode = register_allocation expected_mode in (* CR layouts v4: non-values in arrays *) - let ty = newgenvar Layout.value in + let ty = newgenvar (Layout.value ~why:Array_element) in let to_unify = type_ ty in with_explanation explanation (fun () -> unify_exp_types loc env to_unify (generic_instance ty_expected)); @@ -7334,13 +7371,15 @@ and type_comprehension_expr comprehension. - [{body = sbody; clauses}]: The actual comprehension to be translated. *) - let comprehension_type, container_type, make_texp, {body = sbody; clauses} = + let comprehension_type, container_type, make_texp, + {body = sbody; clauses}, reason = match cexpr with | Cexp_list_comprehension comp -> List_comprehension, Predef.type_list, (fun tcomp -> Texp_list_comprehension tcomp), - comp + comp, + Layout.Type_argument | Cexp_array_comprehension (amut, comp) -> let container_type = match amut with | Mutable -> Predef.type_array @@ -7349,10 +7388,11 @@ and type_comprehension_expr Array_comprehension amut, container_type, (fun tcomp -> Texp_array_comprehension (amut, tcomp)), - comp + comp, + Layout.Array_element in if !Clflags.principal then begin_def (); - let element_ty = newvar Layout.value in + let element_ty = newvar (Layout.value ~why:reason) in unify_exp_types loc env @@ -7457,7 +7497,7 @@ and type_comprehension_iterator in Texp_comp_range { ident; pattern; start; stop; direction } | In seq -> - let item_ty = newvar Layout.any in + let item_ty = newvar (Layout.any ~why:Dummy_layout) in let seq_ty = container_type item_ty in let sequence = (* To understand why we can currently only iterate over [mode_global] @@ -7541,12 +7581,13 @@ let type_expression env layout sexp = {exp with exp_type = desc.val_type} | _ -> exp -let type_representable_expression env sexp = +let type_representable_expression ~why env sexp = let sort = Sort.new_var () in - let exp = type_expression env (Layout.of_sort sort) sexp in + let exp = type_expression env (Layout.of_sort ~why sort) sexp in exp, sort -let type_expression env sexp = type_expression env Layout.any sexp +let type_expression env sexp = + type_expression env (Layout.any ~why:Type_expression_call) sexp (* Error report *) diff --git a/ocaml/typing/typecore.mli b/ocaml/typing/typecore.mli index 859670ed57c..26105952cc7 100644 --- a/ocaml/typing/typecore.mli +++ b/ocaml/typing/typecore.mli @@ -122,6 +122,7 @@ val type_let: val type_expression: Env.t -> Parsetree.expression -> Typedtree.expression val type_representable_expression: + why:Layouts.Layout.concrete_layout_reason -> Env.t -> Parsetree.expression -> Typedtree.expression * sort val type_class_arg_pattern: string -> Env.t -> Env.t -> arg_label -> Parsetree.pattern -> @@ -196,7 +197,7 @@ type error = Datatype_kind.t * Longident.t * (Path.t * Path.t) * (Path.t * Path.t) list | Invalid_format of string | Not_an_object of type_expr * type_forcing_context option - | Not_a_value of Layout.Violation.violation * type_forcing_context option + | Not_a_value of Layout.Violation.t * type_forcing_context option | Undefined_method of type_expr * string * string list option | Undefined_self_method of string * string list | Virtual_class of Longident.t diff --git a/ocaml/typing/typedecl.ml b/ocaml/typing/typedecl.ml index 06ce5c4a8d0..62e10e10fd5 100644 --- a/ocaml/typing/typedecl.ml +++ b/ocaml/typing/typedecl.ml @@ -63,12 +63,12 @@ type error = | Multiple_native_repr_attributes | Cannot_unbox_or_untag_type of native_repr_kind | Deep_unbox_or_untag_attribute of native_repr_kind - | Layout_coherence_check of type_expr * Layout.Violation.violation - | Layout_update_check of Path.t * Layout.Violation.violation + | Layout_coherence_check of type_expr * Layout.Violation.t + | Layout_update_check of Path.t * Layout.Violation.t | Layout_sort of { lloc : layout_sort_loc ; typ : type_expr - ; err : Layout.Violation.violation + ; err : Layout.Violation.t } | Layout_empty_record | Separability of Typedecl_separability.error @@ -87,12 +87,12 @@ exception Error of Location.t * error let layout_of_attributes ~legacy_immediate ~reason attrs = match Layout.of_attributes ~legacy_immediate ~reason attrs with | Ok l -> l - | Error (loc, c) -> raise (Error (loc, Layout_not_enabled c)) + | Error { loc; txt } -> raise (Error (loc, Layout_not_enabled txt)) let layout_of_attributes_default ~legacy_immediate ~reason ~default attrs = match Layout.of_attributes_default ~legacy_immediate ~reason ~default attrs with | Ok l -> l - | Error (loc, c) -> raise (Error (loc, Layout_not_enabled c)) + | Error { loc; txt } -> raise (Error (loc, Layout_not_enabled txt)) let get_unboxed_from_attributes sdecl = let unboxed = Builtin_attributes.has_unboxed sdecl.ptype_attributes in @@ -133,6 +133,7 @@ let enter_type rec_flag env sdecl (id, uid) = in if not needed then env else let arity = List.length sdecl.ptype_params in + let path = Path.Pident id in (* There is some trickiness going on here with the layout. It expands on an old trick used in the manifest of [decl] below. @@ -191,8 +192,8 @@ let enter_type rec_flag env sdecl (id, uid) = (* We set ~legacy_immediate to true because we're looking at a declaration that was already allowed to be [@@immediate] *) layout_of_attributes_default - ~legacy_immediate:true ~reason:(Type_declaration (Pident id)) - ~default:Layout.any + ~legacy_immediate:true ~reason:(Type_declaration path) + ~default:(Layout.any ~why:Initial_typedecl_env) sdecl.ptype_attributes in let decl = @@ -226,8 +227,8 @@ let enter_type rec_flag env sdecl (id, uid) = (fun (param, _) -> let layout = layout_of_attributes_default ~legacy_immediate:false - ~reason:(Type_parameter (Pident id, parameter_name param)) - ~default:Layout.value + ~reason:(Type_parameter (path, parameter_name param)) + ~default:(Layout.value ~why:Type_argument) param.ptyp_attributes in Btype.newgenvar layout) @@ -340,7 +341,7 @@ let set_private_row env loc p decl = (* [make_params] creates sort variables - these can be defaulted away (as in transl_type_decl) or unified with existing sort-variable-free types (as in transl_with_constraint). *) -let make_params env id params = +let make_params env path params = (* Our choice for now is that if you want a parameter of layout any, you have to ask for it with an annotation. Some restriction here seems necessary for backwards compatibility (e.g., we wouldn't want [type 'a id = 'a] to @@ -349,8 +350,9 @@ let make_params env id params = try let layout = layout_of_attributes_default ~legacy_immediate:false - ~reason:(Type_parameter (id, parameter_name sty)) - ~default:(Layout.of_new_sort_var ()) sty.ptyp_attributes + ~reason:(Type_parameter (path, parameter_name sty)) + ~default:(Layout.of_new_sort_var ~why:Unannotated_type_parameter) + sty.ptyp_attributes in (transl_type_param env sty layout, v) with Already_bound -> @@ -407,7 +409,8 @@ let transl_labels env univars closed lbls = {Types.ld_id = ld.ld_id; ld_mutable = ld.ld_mutable; ld_global = ld.ld_global; - ld_layout = Layout.any; (* Updated by [update_label_layouts] *) + ld_layout = Layout.any ~why:Dummy_layout; + (* Updated by [update_label_layouts] *) ld_type = ty; ld_loc = ld.ld_loc; ld_attributes = ld.ld_attributes; @@ -488,7 +491,10 @@ let make_constructor env loc type_path type_params svars sargs sret_type = Btype.iter_type_expr_cstr_args Ctype.generalize args; Ctype.generalize ret_type; let _vars = TyVarEnv.instance_poly_univars env loc univars in - let set_level t = Ctype.unify_var env (Ctype.newvar Layout.any) t in + let set_level t = + Ctype.unify_var env + (Ctype.newvar (Layout.any ~why:Dummy_layout)) t + in Btype.iter_type_expr_cstr_args set_level args; set_level ret_type; end; @@ -646,6 +652,7 @@ let transl_declaration env sdecl (id, uid) = let cty = transl_simple_type env ~closed:no_row Global sty in Some cty, Some cty.ctyp_type in + let any = Layout.any ~why:Initial_typedecl_env in (* layout_default is the layout to use for now as the type_layout when there is no annotation and no manifest. See Note [Default layouts in transl_declaration]. @@ -653,7 +660,7 @@ let transl_declaration env sdecl (id, uid) = let (tkind, kind, layout_default) = match sdecl.ptype_kind with | Ptype_abstract -> - Ttype_abstract, Type_abstract, Layout.value + Ttype_abstract, Type_abstract, Layout.value ~why:Default_type_layout | Ptype_variant scstrs -> if List.exists (fun cstr -> cstr.pcd_res <> None) scstrs then begin match cstrs with @@ -704,7 +711,7 @@ let transl_declaration env sdecl (id, uid) = let tcstrs, cstrs = List.split (List.map make_cstr scstrs) in let rep, layout = if unbox then - Variant_unboxed, Layout.any + Variant_unboxed, any else (* We mark all arg layouts "any" here. They are updated later, after the circular type checks make it safe to check layouts. *) @@ -712,26 +719,27 @@ let transl_declaration env sdecl (id, uid) = Array.map (fun cstr -> match Types.(cstr.cd_args) with - | Cstr_tuple args -> Array.make (List.length args) Layout.any - | Cstr_record _ -> [| Layout.any |]) + | Cstr_tuple args -> + Array.make (List.length args) any + | Cstr_record _ -> [| any |]) (Array.of_list cstrs) ), - Layout.value + Layout.value ~why:Boxed_variant in Ttype_variant tcstrs, Type_variant (cstrs, rep), layout | Ptype_record lbls -> let lbls, lbls' = transl_labels env None true lbls in let rep, layout = if unbox then - Record_unboxed, Layout.any + Record_unboxed, any else (if List.for_all (fun l -> is_float env l.Types.ld_type) lbls' then Record_float - else Record_boxed (Array.make (List.length lbls) Layout.any)), - Layout.value + else Record_boxed (Array.make (List.length lbls) any)), + Layout.value ~why:Boxed_record in Ttype_record lbls, Type_record(lbls', rep), layout | Ptype_open -> - Ttype_open, Type_open, Layout.value + Ttype_open, Type_open, Layout.value ~why:Extensible_variant in let layout = (* - If there's an annotation, we use that. It's checked against @@ -984,8 +992,8 @@ let check_coherence env loc dpath decl = else Ctype.type_layout env ty in - begin match Layout.sub layout' decl.type_layout with - | Ok () -> { decl with type_layout = layout' } + begin match Layout.sub_with_history layout' decl.type_layout with + | Ok layout' -> { decl with type_layout = layout' } | Error v -> raise (Error (loc, Layout_coherence_check (ty,v))) end @@ -1060,13 +1068,13 @@ let default_decls_layout decls = should be replaced with checks at the places where values of those types are constructed. We've been conservative here in the first version. This is the same issue as with arrows. *) -let check_representable ~reason env loc lloc typ = - match Ctype.type_sort ~reason env typ with +let check_representable ~why env loc lloc typ = + match Ctype.type_sort ~why env typ with (* CR layouts: This is not the right place to default to value. Some callers of this do need defaulting, because they, for example, immediately check if the sort is immediate or void. But we should do that in those places, or as part of our higher-level defaulting story. *) - | Ok s -> Layout.default_to_value (Layout.of_sort s) + | Ok s -> Sort.default_to_value s | Error err -> raise (Error (loc,Layout_sort {lloc; typ; err})) (* The [update_x_layouts] functions infer more precise layouts in the type kind, @@ -1087,14 +1095,14 @@ let update_label_layouts env loc lbls named = in let lbls = List.mapi (fun idx (Types.{ld_type; ld_id; ld_loc} as lbl) -> - check_representable ~reason:(Label_declaration ld_id) + check_representable ~why:(Label_declaration ld_id) env ld_loc Record ld_type; let ld_layout = Ctype.type_layout env ld_type in update idx ld_layout; {lbl with ld_layout} ) lbls in - if List.for_all (fun l -> Layout.(equal void l.ld_layout)) lbls then + if List.for_all (fun l -> Layout.is_void_defaulting l.ld_layout) lbls then raise (Error (loc, Layout_empty_record)) else lbls, false (* CR layouts v5: return true for a record with all voids *) @@ -1106,13 +1114,13 @@ let update_constructor_arguments_layouts env loc cd_args layouts = match cd_args with | Types.Cstr_tuple tys -> List.iteri (fun idx (ty,_) -> - check_representable ~reason:(Constructor_declaration idx) + check_representable ~why:(Constructor_declaration idx) env loc Cstr_tuple ty; layouts.(idx) <- Ctype.type_layout env ty) tys; - cd_args, Array.for_all Layout.is_void layouts + cd_args, Array.for_all Layout.is_void_defaulting layouts | Types.Cstr_record lbls -> let lbls, all_void = update_label_layouts env loc lbls None in - layouts.(0) <- Layout.value; + layouts.(0) <- Layout.value ~why:Boxed_record; Types.Cstr_record lbls, all_void (* This function updates layout stored in kinds with more accurate layouts. @@ -1129,7 +1137,7 @@ let update_decl_layout env dpath decl = let update_record_kind loc lbls rep = match lbls, rep with | [Types.{ld_type; ld_id; ld_loc} as lbl], Record_unboxed -> - check_representable ~reason:(Label_declaration ld_id) + check_representable ~why:(Label_declaration ld_id) env ld_loc Record ld_type; let ld_layout = Ctype.type_layout env ld_type in [{lbl with ld_layout}], Record_unboxed, ld_layout @@ -1142,9 +1150,11 @@ let update_decl_layout env dpath decl = sense to use that here? The use of value feels inaccurate, but I think the code that would look at first looks at the rep. *) let lbls = - List.map (fun lbl -> { lbl with ld_layout = Layout.value }) lbls + List.map (fun lbl -> + { lbl with ld_layout = Layout.value ~why:Float_record_field }) + lbls in - lbls, rep, Layout.value + lbls, rep, Layout.value ~why:Boxed_record | (([] | (_ :: _)), Record_unboxed | _, Record_inlined _) -> assert false in @@ -1156,13 +1166,13 @@ let update_decl_layout env dpath decl = match cd_args with | Cstr_tuple [ty,_] -> begin (* CR layouts: check_representable should return the sort *) - check_representable ~reason:(Constructor_declaration 0) + check_representable ~why:(Constructor_declaration 0) env cd_loc Cstr_tuple ty; let layout = Ctype.type_layout env ty in cstrs, Variant_unboxed, layout end | Cstr_record [{ld_type; ld_id; ld_loc} as lbl] -> begin - check_representable ~reason:(Label_declaration ld_id) + check_representable ~why:(Label_declaration ld_id) env ld_loc Record ld_type; let ld_layout = Ctype.type_layout env ld_type in [{ cstr with Types.cd_args = @@ -1183,9 +1193,7 @@ let update_decl_layout env dpath decl = (idx+1,cstr::cstrs,all_voids && all_void) ) (0,[],true) cstrs in - let layout = - if all_voids then Layout.immediate else Layout.value - in + let layout = Layout.for_boxed_variant ~all_voids in List.rev cstrs, rep, layout | (([] | (_ :: _)), Variant_unboxed | _, Variant_extensible) -> assert false @@ -1194,7 +1202,7 @@ let update_decl_layout env dpath decl = let new_decl, new_layout = match decl.type_kind with | Type_abstract -> decl, decl.type_layout | Type_open -> - let type_layout = Layout.value in + let type_layout = Layout.value ~why:Extensible_variant in { decl with type_layout }, type_layout | Type_record (lbls, rep) -> let lbls, rep, type_layout = update_record_kind decl.type_loc lbls rep in @@ -1284,7 +1292,8 @@ let check_well_founded_manifest env loc path decl = let args = (* The layouts here shouldn't matter for the purposes of [check_well_founded] *) - List.map (fun _ -> Ctype.newvar Layout.any) decl.type_params + List.map (fun _ -> Ctype.newvar (Layout.any ~why:Dummy_layout)) + decl.type_params in check_well_founded env loc path (Path.same path) (Ctype.newconstr path args) @@ -1539,10 +1548,7 @@ let transl_type_decl env rec_flag sdecl_list = layout checks *) List.iter (fun (checks,loc) -> List.iter (fun (ty,layout) -> - match - Ctype.constrain_type_layout ~reason:Dummy_reason_result_ignored - new_env ty layout - with + match Ctype.constrain_type_layout new_env ty layout with | Ok _ -> () | Error err -> let err = Errortrace.unification_error ~trace:[Bad_layout (ty,err)] in @@ -1610,7 +1616,7 @@ let transl_extension_constructor ~scope env type_path type_params | Cstr_tuple args -> List.length args | Cstr_record _ -> 1 in - let layouts = Array.make num_args Layout.any in + let layouts = Array.make num_args (Layout.any ~why:Dummy_layout) in let args, constant = update_constructor_arguments_layouts env sext.pext_loc args layouts in @@ -2142,9 +2148,8 @@ let transl_with_constraint id ?fixed_row_path ~sig_env ~sig_decl ~outer_env sig_decl.type_kind, sig_decl.type_unboxed_default, sig_decl.type_layout else (* CR layouts v2: this is a gross hack. See the comments in the - [Ptyp_package] case of [Typetexp.transl_type_aux]. - This seems just wrong to RAE. *) - let layout = Layout.value in + [Ptyp_package] case of [Typetexp.transl_type_aux]. *) + let layout = Layout.value ~why:Package_hack in (* Layout.(of_attributes ~default:value sdecl.ptype_attributes) *) Type_abstract, false, layout in @@ -2206,7 +2211,7 @@ let transl_with_constraint id ?fixed_row_path ~sig_env ~sig_decl ~outer_env let layout_annotation = layout_of_attributes ~legacy_immediate:false - ~reason:(With_constraint sdecl.ptype_loc) + ~reason:(With_constraint sdecl.ptype_name.txt) sdecl.ptype_attributes in Ctype.end_def(); @@ -2262,13 +2267,14 @@ let approx_type_decl sdecl_list = to write [@@immediate] on declarations. *) layout_of_attributes_default ~legacy_immediate:true ~reason:(Type_declaration (Pident id)) - ~default:Layout.value sdecl.ptype_attributes + ~default:(Layout.value ~why:Default_type_layout) + sdecl.ptype_attributes in let params = List.map (fun (styp,_) -> layout_of_attributes_default ~legacy_immediate:false ~reason:(Type_parameter (Pident id, parameter_name styp)) - ~default:Layout.value + ~default:(Layout.value ~why:Type_argument) styp.ptyp_attributes) sdecl.ptype_params in diff --git a/ocaml/typing/typedecl.mli b/ocaml/typing/typedecl.mli index 5bd71146d56..6bbb84da6f0 100644 --- a/ocaml/typing/typedecl.mli +++ b/ocaml/typing/typedecl.mli @@ -102,12 +102,12 @@ type error = | Multiple_native_repr_attributes | Cannot_unbox_or_untag_type of native_repr_kind | Deep_unbox_or_untag_attribute of native_repr_kind - | Layout_coherence_check of type_expr * Layout.Violation.violation - | Layout_update_check of Path.t * Layout.Violation.violation + | Layout_coherence_check of type_expr * Layout.Violation.t + | Layout_update_check of Path.t * Layout.Violation.t | Layout_sort of { lloc : layout_sort_loc ; typ : type_expr - ; err : Layout.Violation.violation + ; err : Layout.Violation.t } | Layout_empty_record | Separability of Typedecl_separability.error diff --git a/ocaml/typing/typedecl_separability.ml b/ocaml/typing/typedecl_separability.ml index 618fe309556..d0126f258c9 100644 --- a/ocaml/typing/typedecl_separability.ml +++ b/ocaml/typing/typedecl_separability.ml @@ -479,10 +479,11 @@ let worst_msig decl = List.map (fun _ -> Deepsep) decl.type_params array optimization and this entire file at that point. *) let msig_of_external_type env decl = let check_layout = - Ctype.check_decl_layout ~reason:Dummy_reason_result_ignored env decl + Ctype.check_decl_layout env decl in - if Result.is_error (check_layout Layout.value) - || Result.is_ok (check_layout Layout.immediate64) + if Result.is_error (check_layout (Layout.value ~why:Separability_check)) + || Result.is_ok + (check_layout (Layout.immediate64 ~why:Separability_check)) then best_msig decl else worst_msig decl diff --git a/ocaml/typing/typemod.ml b/ocaml/typing/typemod.ml index 9d2bb045b40..9d0756ec531 100644 --- a/ocaml/typing/typemod.ml +++ b/ocaml/typing/typemod.ml @@ -576,10 +576,12 @@ let merge_constraint initial_env loc sg lid constr = { type_params = (* layout any is fine on the params because they get thrown away below *) - List.map (fun _ -> Btype.newgenvar Layout.any) sdecl.ptype_params; + List.map + (fun _ -> Btype.newgenvar (Layout.any ~why:Dummy_layout)) + sdecl.ptype_params; type_arity = arity; type_kind = Type_abstract; - type_layout = Layout.value; + type_layout = Layout.value ~why:(Unknown "merge_constraint"); type_private = Private; type_manifest = None; type_variance = @@ -2636,7 +2638,8 @@ and type_structure ?(toplevel = None) funct_body anchor env sstr = near the top of [execute_phrase] in [opttoploop.ml]. *) let expr, sort = Builtin_attributes.warning_scope attrs - (fun () -> Typecore.type_representable_expression env sexpr) + (fun () -> Typecore.type_representable_expression + ~why:Structure_item_expression env sexpr) in Tstr_eval (expr, sort, attrs), [], shape_map, env | Pstr_value(rec_flag, sdefs) -> @@ -2661,9 +2664,9 @@ and type_structure ?(toplevel = None) funct_body anchor env sstr = (* CR layouts v5: this layout check has the effect of defaulting the sort of top-level bindings to value, which will change. *) - if not (Layout.(equate (of_sort sort) value)) then - raise (Error (loc, env, - Toplevel_nonvalue (Ident.name id,sort))) + if not Sort.(equate sort value) + then raise (Error (loc, env, + Toplevel_nonvalue (Ident.name id,sort))) ) modes; let (first_loc, _, _) = List.hd modes in @@ -3167,7 +3170,8 @@ let type_package env m p fl = List.iter (fun (n, ty) -> (* CR layouts v5: relax value requirement. *) - try Ctype.unify env ty (Ctype.newvar Layout.value) + try Ctype.unify env ty + (Ctype.newvar (Layout.value ~why:Structure_element)) with Ctype.Unify _ -> raise (Error(modl.mod_loc, env, Scoping_pack (n,ty)))) fl'; @@ -3615,7 +3619,7 @@ let report_error ~loc _env = function | Toplevel_nonvalue (id, sort) -> Location.errorf ~loc "@[Top-level module bindings must have layout value, but@ \ - %s has layout@ %a.@]" id Layout.format (Layout.of_sort sort) + %s has layout@ %a.@]" id Sort.format sort let report_error env ~loc err = Printtyp.wrap_printing_env ~error:true env diff --git a/ocaml/typing/typeopt.ml b/ocaml/typing/typeopt.ml index 3b4df782f68..1978a50b75f 100644 --- a/ocaml/typing/typeopt.ml +++ b/ocaml/typing/typeopt.ml @@ -26,7 +26,7 @@ open Lambda the void sanity check. When we're ready to take that out, remove the errors stuff. *) type error = - Non_value_layout of type_expr * Layout.Violation.violation + Non_value_layout of type_expr * Layout.Violation.t exception Error of Location.t * error @@ -80,11 +80,10 @@ let is_always_gc_ignorable env ty = immediate64 types as gc_ignorable, because bytecode is intended to be platform independent. *) if !Clflags.native_code && Sys.word_size = 64 - then Layout.immediate64 - else Layout.immediate + then Layout.immediate64 ~why:Gc_ignorable_check + else Layout.immediate ~why:Gc_ignorable_check in - Result.is_ok - (Ctype.check_type_layout ~reason:V1_safety_check env ty layout) + Result.is_ok (Ctype.check_type_layout env ty layout) let maybe_pointer_type env ty = let ty = scrape_ty env ty in @@ -255,20 +254,20 @@ let rec value_kind env ~loc ~visited ~depth ~num_nodes_visited ty This should be understood, but for now I'm doing the simple fall back thing so I can test the performance difference. *) - match Ctype.check_type_layout ~reason:V1_safety_check env scty Layout.value + match Ctype.check_type_layout env scty (Layout.value ~why:V1_safety_check) with | Ok _ -> () | Error _ -> match - Ctype.(check_type_layout ~reason:V1_safety_check env - (correct_levels ty) Layout.value) + Ctype.(check_type_layout env + (correct_levels ty) (Layout.value ~why:V1_safety_check)) with | Ok _ -> () - | Error e -> - if e.missing_cmi then - () (* CR layouts v1.5: stop allowing missing cmis *) - else - raise (Error (loc, Non_value_layout (ty, e))) + | Error violation -> + if not (Layout.Violation.is_missing_cmi violation) + then raise (Error (loc, Non_value_layout (ty, violation))) + (* CR layouts v1.5: stop allowing missing cmis *) + end; match get_desc scty with | Tconstr(p, _, _) when Path.same p Predef.path_int -> diff --git a/ocaml/typing/types.mli b/ocaml/typing/types.mli index 84e760d6d01..8128337d97e 100644 --- a/ocaml/typing/types.mli +++ b/ocaml/typing/types.mli @@ -787,7 +787,7 @@ type label_description = (** The special value we assign to lbl_pos for label descriptions corresponding to void types, because they can't sensibly be projected. - CR-someday layouts: This should be removed once we have unarization, as it + CR layouts v5: This should be removed once we have unarization, as it will be up to a later stage of the compiler to erase void. *) val lbl_pos_void : int diff --git a/ocaml/typing/typetexp.ml b/ocaml/typing/typetexp.ml index 1fa4c6fefdf..9b062cebebc 100644 --- a/ocaml/typing/typetexp.ml +++ b/ocaml/typing/typetexp.ml @@ -57,9 +57,9 @@ type error = | Unsupported_extension of Language_extension.t | Polymorphic_optional_param | Non_value of - {vloc : value_loc; typ : type_expr; err : Layout.Violation.violation} + {vloc : value_loc; typ : type_expr; err : Layout.Violation.t} | Non_sort of - {vloc : sort_loc; typ : type_expr; err : Layout.Violation.violation} + {vloc : sort_loc; typ : type_expr; err : Layout.Violation.t} exception Error of Location.t * Env.t * error exception Error_forward of Location.error @@ -208,7 +208,7 @@ end = struct ~finally:(fun () -> univars := old_univars) let make_poly_univars vars = - List.map (fun name -> name, newvar ~name Layout.value) vars + List.map (fun name -> name, newvar ~name (Layout.value ~why:Univar)) vars let check_poly_univars env loc vars = vars |> List.iter (fun (_, v) -> generalize v); @@ -294,7 +294,7 @@ end = struct TyVarMap.iter (fun name (ty, loc) -> if flavor = Unification || is_in_scope name then - let v = new_global_var Layout.any in + let v = new_global_var (Layout.any ~why:Dummy_layout) in let snap = Btype.snapshot () in if try unify env v ty; true with _ -> Btype.backtrack snap; false then try @@ -304,7 +304,7 @@ end = struct raise(Error(loc, env, Unbound_type_variable ("'"^name, get_in_scope_names ()))); - let v2 = new_global_var Layout.any in + let v2 = new_global_var (Layout.any ~why:Dummy_layout) in r := (loc, v, v2) :: !r; add name v2) !used_variables; @@ -441,8 +441,10 @@ and transl_type_aux env policy mode styp = | None -> match styp.ptyp_desc with Ptyp_any -> - let ty = TyVarEnv.new_anon_var styp.ptyp_loc env Layout.any policy in - ctyp Ttyp_any ty + let ty = + TyVarEnv.new_anon_var styp.ptyp_loc env (Layout.any ~why:Wildcard) policy + in + ctyp Ttyp_any ty | Ptyp_var name -> let ty = if not (valid_tyvar_name name) then @@ -450,7 +452,8 @@ and transl_type_aux env policy mode styp = begin try TyVarEnv.lookup_local name with Not_found -> - let v = TyVarEnv.new_var ~name Layout.any policy in + let v = TyVarEnv.new_var ~name + (Layout.any ~why:Unification_var) policy in TyVarEnv.remember_used name v styp.ptyp_loc; v end @@ -490,8 +493,8 @@ and transl_type_aux env policy mode styp = to have a representable layout. See comment in [Ctype.filter_arrow]. *) begin match - Ctype.type_sort ~reason:Function_argument env arg_ty, - Ctype.type_sort ~reason:Function_result env ret_cty.ctyp_type + Ctype.type_sort ~why:Function_argument env arg_ty, + Ctype.type_sort ~why:Function_result env ret_cty.ctyp_type with | Ok _, Ok _ -> () | Error e, _ -> @@ -515,8 +518,8 @@ and transl_type_aux env policy mode styp = List.iter (fun {ctyp_type; ctyp_loc} -> (* CR layouts v5: remove value requirement *) match - constrain_type_layout ~reason:(Fixed_layout Tuple_element) - env ctyp_type Layout.value + constrain_type_layout + env ctyp_type (Layout.value ~why:Tuple_element) with | Ok _ -> () | Error e -> @@ -615,10 +618,13 @@ and transl_type_aux env policy mode styp = (row_fields row) in (* NB: row is always non-static here; more is thus never Tnil *) - let more = TyVarEnv.new_var Layout.value policy in + let more = + TyVarEnv.new_var (Layout.value ~why:Row_variable) policy + in let row = create_row ~fields ~more - ~closed:true ~fixed:None ~name:(Some (path, ty_args)) in + ~closed:true ~fixed:None ~name:(Some (path, ty_args)) + in newty (Tvariant row) | Tobject (fi, _) -> let _, tv = flatten_fields fi in @@ -640,7 +646,7 @@ and transl_type_aux env policy mode styp = ty with Not_found -> if !Clflags.principal then begin_def (); - let t = newvar Layout.any in + let t = newvar (Layout.any ~why:Dummy_layout) in TyVarEnv.remember_used alias t styp.ptyp_loc; let ty = transl_type env policy mode st in begin try unify_var env t ty.ctyp_type with Unify err -> @@ -667,7 +673,7 @@ and transl_type_aux env policy mode styp = let name = ref None in let mkfield l f = newty (Tvariant (create_row ~fields:[l,f] - ~more:(newvar Layout.value) + ~more:(newvar (Layout.value ~why:Row_variable)) ~closed:true ~fixed:None ~name:None)) in let hfields = Hashtbl.create 17 in let add_typed_field loc l f = @@ -699,8 +705,8 @@ and transl_type_aux env policy mode styp = (* CR layouts: at some point we'll allow different layouts in polymorphic variants. *) match - constrain_type_layout ~reason:Dummy_reason_result_ignored - env ctyp_type Layout.value + constrain_type_layout env ctyp_type + (Layout.value ~why:Polymorphic_variant_field) with | Ok _ -> () | Error e -> @@ -768,8 +774,10 @@ and transl_type_aux env policy mode styp = create_row ~fields ~more ~closed:(closed = Closed) ~fixed:None ~name in let more = - if Btype.static_row (make_row (newvar Layout.value)) then newty Tnil - else TyVarEnv.new_var Layout.value policy + if Btype.static_row + (make_row (newvar (Layout.value ~why:Row_variable))) + then newty Tnil + else TyVarEnv.new_var (Layout.value ~why:Row_variable) policy in let ty = newty (Tvariant (make_row more)) in ctyp (Ttyp_variant (tfields, closed, present)) ty @@ -788,7 +796,7 @@ and transl_type_aux env policy mode styp = let ty_list = TyVarEnv.check_poly_univars env styp.ptyp_loc new_univars in let ty_list = List.filter (fun v -> deep_occur v ty) ty_list in let ty' = Btype.newgenty (Tpoly(ty, ty_list)) in - unify_var env (newvar Layout.any) ty'; + unify_var env (newvar (Layout.any ~why:Dummy_layout)) ty'; ctyp (Ttyp_poly (vars, cty)) ty' | Ptyp_package (p, l) -> (* CR layouts: right now we're doing a real gross hack where we demand @@ -808,8 +816,7 @@ and transl_type_aux env policy mode styp = ) l in List.iter (fun (s,{ctyp_type=ty}) -> match - Ctype.constrain_type_layout ~reason:(Fixed_layout Package_hack) - env ty Layout.value + Ctype.constrain_type_layout env ty (Layout.value ~why:Package_hack) with | Ok _ -> () | Error e -> @@ -855,8 +862,8 @@ and transl_fields env policy o fields = in begin match - constrain_type_layout ~reason:(Fixed_layout Object_field) - env ty1.ctyp_type Layout.value + constrain_type_layout + env ty1.ctyp_type (Layout.value ~why:Object_field) with | Ok _ -> () | Error e -> @@ -903,7 +910,7 @@ and transl_fields env policy o fields = let ty_init = match o with | Closed -> newty Tnil - | Open -> TyVarEnv.new_var Layout.value policy + | Open -> TyVarEnv.new_var (Layout.value ~why:Row_variable) policy in let ty = List.fold_left (fun ty (s, ty') -> newty (Tfield (s, field_public, ty', ty))) ty_init fields in diff --git a/ocaml/typing/typetexp.mli b/ocaml/typing/typetexp.mli index 5af22af190a..df9415af7b9 100644 --- a/ocaml/typing/typetexp.mli +++ b/ocaml/typing/typetexp.mli @@ -98,9 +98,9 @@ type error = | Unsupported_extension of Language_extension.t | Polymorphic_optional_param | Non_value of - {vloc : value_loc; typ : type_expr; err : Layout.Violation.violation} + {vloc : value_loc; typ : type_expr; err : Layout.Violation.t} | Non_sort of - {vloc : sort_loc; typ : type_expr; err : Layout.Violation.violation} + {vloc : sort_loc; typ : type_expr; err : Layout.Violation.t} exception Error of Location.t * Env.t * error diff --git a/ocaml/utils/misc.ml b/ocaml/utils/misc.ml index 4f747f4bb05..5ca4d768b66 100644 --- a/ocaml/utils/misc.ml +++ b/ocaml/utils/misc.ml @@ -192,6 +192,10 @@ module Stdlib = struct module Option = struct type 'a t = 'a option + let first_some a b = match a with + | Some _ -> a + | None -> b () + let print print_contents ppf t = match t with | None -> Format.pp_print_string ppf "None" diff --git a/ocaml/utils/misc.mli b/ocaml/utils/misc.mli index fbfecce5e69..a93cc39f5d3 100644 --- a/ocaml/utils/misc.mli +++ b/ocaml/utils/misc.mli @@ -149,6 +149,9 @@ module Stdlib : sig module Option : sig type 'a t = 'a option + (* short circuits if the first argument really is a [Some] *) + val first_some : 'a option -> (unit -> 'a option) -> 'a option + val print : (Format.formatter -> 'a -> unit) -> Format.formatter From 0c13643be40a5a8f255522d4fd96807dcbb631ff Mon Sep 17 00:00:00 2001 From: Nick Roberts Date: Wed, 31 May 2023 18:21:18 -0400 Subject: [PATCH 06/30] Erasability namespace for Jane Syntax attributes/extensions (#1421) * Add `erasable` and `non_erasable` namespaces for embeddings * Add an attribute test * Rename namespace to erasability * Change Jane_syntax_parsing to take a Feature.t instead of a string * Minimize diff * Update ocaml/parsing/jane_syntax.ml Co-authored-by: Antal Spector-Zabusky * Update ocaml/parsing/jane_syntax.ml Co-authored-by: Antal Spector-Zabusky * Apply suggestions from code review Co-authored-by: Antal Spector-Zabusky * Respond to review comments * make comprehensions examples look non-erasable * hide Erasability definition from mli and move docs accordingly * Update ocaml/parsing/jane_syntax.ml Co-authored-by: Antal Spector-Zabusky * update tests according to review * Actually hide erasability --------- Co-authored-by: Antal Spector-Zabusky --- ocaml/parsing/builtin_attributes.ml | 40 ++- ocaml/parsing/jane_syntax.ml | 68 +++--- ocaml/parsing/jane_syntax_parsing.ml | 228 +++++++++++++----- ocaml/parsing/jane_syntax_parsing.mli | 46 +++- .../user_error1.compilers.reference | 8 +- .../tests/jane-modular-syntax/user_error1.ml | 2 +- .../user_error2.compilers.reference | 8 +- .../tests/jane-modular-syntax/user_error2.ml | 2 +- .../user_error3.compilers.reference | 8 +- .../tests/jane-modular-syntax/user_error3.ml | 2 +- .../user_error3_1.compilers.reference | 4 + .../jane-modular-syntax/user_error3_1.ml | 9 + .../user_error3_2.compilers.reference | 4 + .../jane-modular-syntax/user_error3_2.ml | 9 + .../user_error3_3.compilers.reference | 4 + .../jane-modular-syntax/user_error3_3.ml | 9 + .../user_error4.compilers.reference | 2 +- .../tests/jane-modular-syntax/user_error4.ml | 2 +- .../user_error5.compilers.reference | 2 +- .../user_error6.compilers.reference | 5 +- .../tests/jane-modular-syntax/user_error6.ml | 2 +- ...user_error7_attributes.compilers.reference | 4 + .../user_error7_attributes.ml | 25 ++ ...er_error7.ml => user_error7_extensions.ml} | 0 24 files changed, 360 insertions(+), 133 deletions(-) create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.compilers.reference create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.ml create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.compilers.reference create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.ml create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.compilers.reference create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.ml create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.compilers.reference create mode 100644 ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.ml rename ocaml/testsuite/tests/jane-modular-syntax/{user_error7.ml => user_error7_extensions.ml} (100%) diff --git a/ocaml/parsing/builtin_attributes.ml b/ocaml/parsing/builtin_attributes.ml index 1721e619928..04c48ee64e9 100644 --- a/ocaml/parsing/builtin_attributes.ml +++ b/ocaml/parsing/builtin_attributes.ml @@ -108,12 +108,42 @@ let builtin_attrs = ; "tail_mod_cons"; "ocaml.tail_mod_cons" ] -let builtin_attrs = - let tbl = Hashtbl.create 128 in - List.iter (fun attr -> Hashtbl.add tbl attr ()) builtin_attrs; - tbl +(* nroberts: When we upstream the builtin-attribute whitelisting, we shouldn't + upstream the "jane" prefix. + - Internally, we use "jane.*" to encode our changes to the parsetree, + and our compiler should not drop these attributes. + - Upstream, ppxes may produce attributes with the "jane.*" prefix. + The upstream compiler does not use these attributes. We want it to be + able to drop these attributes without a warning. + + It's an error for an upstream ppx to create an attribute that corresponds to + a *non-erasable* Jane language extension, like list comprehensions, which + should never reach the upstream compiler. So, we distinguish that in the + attribute prefix: upstream ppxlib will error out if it sees a ppx creating a + "jane.non_erasable" attribute and be happy to accept a "jane.erasable" + attribute. Meanwhile, an internal patched version of ppxlib will be happy for + a ppx to produce either of these attributes. +*) +let builtin_attr_prefixes = + [ "jane" + ] -let is_builtin_attr s = Hashtbl.mem builtin_attrs s +let is_builtin_attr = + let builtin_attrs = + let tbl = Hashtbl.create 128 in + List.iter + (fun attr -> Hashtbl.add tbl attr ()) + (builtin_attr_prefixes @ builtin_attrs); + tbl + in + let builtin_attr_prefixes_with_trailing_dot = + List.map (fun x -> x ^ ".") builtin_attr_prefixes + in + fun s -> + Hashtbl.mem builtin_attrs s + || List.exists + (fun prefix -> String.starts_with ~prefix s) + builtin_attr_prefixes_with_trailing_dot type attr_tracking_time = Parser | Invariant_check diff --git a/ocaml/parsing/jane_syntax.ml b/ocaml/parsing/jane_syntax.ml index ae91667e151..236ab4ce9b8 100644 --- a/ocaml/parsing/jane_syntax.ml +++ b/ocaml/parsing/jane_syntax.ml @@ -12,23 +12,25 @@ open Jane_syntax_parsing that both [comprehensions] and [immutable_arrays] are enabled. But our general mechanism for checking for enabled extensions (in [of_ast]) won't work well here: it triggers when converting from - e.g. [[%jane.comprehensions.array] ...] to the comprehensions-specific - AST. But if we spot a [[%jane.comprehensions.immutable]], there is no - expression to translate. So we just check for the immutable arrays extension - when processing a comprehension expression for an immutable array. + e.g. [[%jane.non_erasable.comprehensions.array] ...] to the + comprehensions-specific AST. But if we spot a + [[%jane.non_erasable.comprehensions.immutable]], there is no expression to + translate. So we just check for the immutable arrays extension when + processing a comprehension expression for an immutable array. Note [Wrapping with make_entire_jane_syntax] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The topmost node in the encoded AST must always look like e.g. - [%jane.comprehensions]. This allows the decoding machinery to know what - extension is being used and what function to call to do the decoding. - Accordingly, during encoding, after doing the hard work of converting the - extension syntax tree into e.g. Parsetree.expression, we need to make a final - step of wrapping the result in an [%jane.xyz] node. Ideally, this step would - be done by part of our general structure, like we separate [of_ast] and - [of_ast_internal] in the decode structure; this design would make it - structurally impossible/hard to forget taking this final step. + [%jane.non_erasable.comprehensions]. (More generally, + [%jane.ERASABILITY.FEATURE] or [@jane.ERASABILITY.FEATURE].) This allows the + decoding machinery to know what extension is being used and what function to + call to do the decoding. Accordingly, during encoding, after doing the hard + work of converting the extension syntax tree into e.g. Parsetree.expression, + we need to make a final step of wrapping the result in a [%jane.*.xyz] node. + Ideally, this step would be done by part of our general structure, like we + separate [of_ast] and [of_ast_internal] in the decode structure; this design + would make it structurally impossible/hard to forget taking this final step. However, the final step is only one line of code (a call to [make_entire_jane_syntax]), but yet the name of the feature varies, as does @@ -43,7 +45,8 @@ module With_attributes = With_attributes (** List and array comprehensions *) module Comprehensions = struct - let extension_string = Language_extension.to_string Comprehensions + let feature : Feature.t = Language_extension Comprehensions + let extension_string = Feature.extension_component feature type iterator = | Range of { start : expression @@ -93,7 +96,7 @@ module Comprehensions = struct let comprehension_expr names x = AST.wrap_desc Expression ~attrs:[] ~loc:x.pexp_loc @@ - AST.make_jane_syntax Expression (extension_string :: names) x + AST.make_jane_syntax Expression feature names x (** First, we define how to go from the nice AST to the OCaml AST; this is the [expr_of_...] family of expressions, culminating in @@ -142,7 +145,7 @@ module Comprehensions = struct let expr_of ~loc cexpr = (* See Note [Wrapping with make_entire_jane_syntax] *) - AST.make_entire_jane_syntax Expression ~loc extension_string (fun () -> + AST.make_entire_jane_syntax Expression ~loc feature (fun () -> match cexpr with | Cexp_list_comprehension comp -> expr_of_comprehension ~type_:["list"] comp @@ -180,7 +183,7 @@ module Comprehensions = struct Location.errorf ~loc "Unknown, unexpected, or malformed@ comprehension embedded term %a" Embedded_name.pp_quoted_name - Embedded_name.(extension_string :: subparts) + (Embedded_name.of_feature feature subparts) | No_clauses -> Location.errorf ~loc "Tried to desugar a comprehension with no clauses" @@ -200,11 +203,14 @@ module Comprehensions = struct attribute removed. *) let expand_comprehension_extension_expr expr = match find_and_remove_jane_syntax_attribute expr.pexp_attributes with - | Some (comprehensions :: names, attributes) - when String.equal comprehensions extension_string -> - names, { expr with pexp_attributes = attributes } - | Some (ext_name, _) -> - Desugaring_error.raise expr (Non_comprehension_embedding ext_name) + | Some (ext_name, attributes) -> begin + match Jane_syntax_parsing.Embedded_name.components ext_name with + | comprehensions :: names + when String.equal comprehensions extension_string -> + names, { expr with pexp_attributes = attributes } + | _ :: _ -> + Desugaring_error.raise expr (Non_comprehension_embedding ext_name) + end | None -> Desugaring_error.raise expr Non_embedding @@ -278,12 +284,12 @@ module Immutable_arrays = struct type nonrec pattern = | Iapat_immutable_array of pattern list - let extension_string = Language_extension.to_string Immutable_arrays + let feature : Feature.t = Language_extension Immutable_arrays let expr_of ~loc = function | Iaexp_immutable_array elts -> (* See Note [Wrapping with make_entire_jane_syntax] *) - AST.make_entire_jane_syntax Expression ~loc extension_string (fun () -> + AST.make_entire_jane_syntax Expression ~loc feature (fun () -> Ast_helper.Exp.array elts) (* Returns remaining unconsumed attributes *) @@ -294,7 +300,7 @@ module Immutable_arrays = struct let pat_of ~loc = function | Iapat_immutable_array elts -> (* See Note [Wrapping with make_entire_jane_syntax] *) - AST.make_entire_jane_syntax Pattern ~loc extension_string (fun () -> + AST.make_entire_jane_syntax Pattern ~loc feature (fun () -> Ast_helper.Pat.array elts) (* Returns remaining unconsumed attributes *) @@ -311,13 +317,13 @@ module Include_functor = struct type structure_item = | Ifstr_include_functor of include_declaration - let extension_string = Language_extension.to_string Include_functor + let feature : Feature.t = Language_extension Include_functor let sig_item_of ~loc = function | Ifsig_include_functor incl -> (* See Note [Wrapping with make_entire_jane_syntax] *) - AST.make_entire_jane_syntax Signature_item ~loc extension_string - (fun () -> Ast_helper.Sig.include_ incl) + AST.make_entire_jane_syntax Signature_item ~loc feature (fun () -> + Ast_helper.Sig.include_ incl) let of_sig_item sigi = match sigi.psig_desc with | Psig_include incl -> Ifsig_include_functor incl @@ -326,8 +332,8 @@ module Include_functor = struct let str_item_of ~loc = function | Ifstr_include_functor incl -> (* See Note [Wrapping with make_entire_jane_syntax] *) - AST.make_entire_jane_syntax Structure_item ~loc extension_string - (fun () -> Ast_helper.Str.include_ incl) + AST.make_entire_jane_syntax Structure_item ~loc feature (fun () -> + Ast_helper.Str.include_ incl) let of_str_item stri = match stri.pstr_desc with | Pstr_include incl -> Ifstr_include_functor incl @@ -339,7 +345,7 @@ module Strengthen = struct type nonrec module_type = { mty : Parsetree.module_type; mod_id : Longident.t Location.loc } - let extension_string = Language_extension.to_string Module_strengthening + let feature : Feature.t = Language_extension Module_strengthening (* Encoding: [S with M] becomes [functor (_ : S) -> (module M)], where the [(module M)] is a [Pmty_alias]. This isn't syntax we can write, but @@ -347,7 +353,7 @@ module Strengthen = struct let mty_of ~loc { mty; mod_id } = (* See Note [Wrapping with make_entire_jane_syntax] *) - AST.make_entire_jane_syntax Module_type ~loc extension_string (fun () -> + AST.make_entire_jane_syntax Module_type ~loc feature (fun () -> Ast_helper.Mty.functor_ (Named (Location.mknoloc None, mty)) (Ast_helper.Mty.alias mod_id)) diff --git a/ocaml/parsing/jane_syntax_parsing.ml b/ocaml/parsing/jane_syntax_parsing.ml index 67a87be6c3e..79ca732278d 100644 --- a/ocaml/parsing/jane_syntax_parsing.ml +++ b/ocaml/parsing/jane_syntax_parsing.ml @@ -7,23 +7,30 @@ of the syntax indicated by the attribute. 2. As a pair of an extension node and an AST item that serves as the "body". Here, the "pair" is embedded as a pair-like construct in the relevant AST - category, e.g. [include sig [%%extension.EXTNAME];; BODY end] for + category, e.g. [include sig [%jane.ERASABILITY.EXTNAME];; BODY end] for signature items. - In particular, for an extension named [EXTNAME] (i.e., one - that is enabled by [-extension EXTNAME] on the command line), the attribute - (if used) must be [[@jane.EXTNAME]], and the extension (if used) must be - [[%jane.EXTNAME]]. For built-in syntax, we use [_builtin] - instead of an extension name. + In particular, for an language extension named [EXTNAME] (i.e., one that is + enabled by [-extension EXTNAME] on the command line), the attribute (if + used) must be [[@jane.ERASABILITY.EXTNAME]], and the extension node (if + used) must be [[%jane.ERASABILITY.EXTNAME]]. For built-in syntax, we use + [_builtin] instead of an language extension name. + + The [ERASABILITY] component indicates to tools such as ocamlformat and + ppxlib whether or not the attribute is erasable. See the documentation of + [Erasability] for more information on how tools make use of this + information. In the below example, we use attributes an examples, but it applies equally to extensions. We also provide utilities for further desugaring similar applications where the embeddings have the longer form - [[@jane.FEATNAME.ID1.ID2.….IDn]] (with the outermost one being the [n = 0] - case), as these might be used inside the [EXPR]. (For example, within the - outermost [[@jane.comprehensions]] term for list and array comprehensions, - we can also use [[@jane.comprehensions.list]], - [[@jane.comprehensions.array]], [[@jane.comprehensions.for.in]], etc.). + [[@jane.ERASABILITY.FEATNAME.ID1.ID2.….IDn]] (with the outermost one being + the [n = 0] case), as these might be used inside the [EXPR]. (For example, + within the outermost [[@jane.non_erasable.comprehensions]] term for list and + array comprehensions, we can also use + [[@jane.non_erasable.comprehensions.list]], + [[@jane.non_erasable.comprehensions.array]], + [[@jane.non_erasable.comprehensions.for.in]], etc.). As mentioned, we represent terms as a "pair" and don't use the extension node or attribute payload; this is so that ppxen can see inside these @@ -42,8 +49,8 @@ We provide one module per syntactic category (e.g., [Expression]), of module type [AST]. They also provide some simple machinery for working with the - general [@jane.FEATNAME.ID1.ID2.….IDn] wrapped forms. To construct one, we - provide [make_jane_syntax]; to destructure one, we provide + general [@jane.ERASABILITY.FEATNAME.ID1.ID2.….IDn] wrapped forms. To + construct one, we provide [make_jane_syntax]; to destructure one, we provide [match_jane_syntax] (which we expose via [make_of_ast]). Users of this module still have to write the transformations in both directions for all new syntax, lowering it to extension nodes or attributes and then lifting it @@ -88,6 +95,8 @@ module Feature : sig val extension_component : t -> string val of_component : string -> (t, error) result + + val is_erasable : t -> bool end = struct type t = Language_extension of Language_extension.t | Builtin @@ -119,11 +128,14 @@ end = struct Error (Disabled_extension ext) | None -> Error (Unknown_extension str) -end -(* FUTURE-PROOFING: We're about to add builtin stuff; delete this ignore-only - binding when we do. *) -let _ = Feature.extension_component + let is_erasable = function + | Language_extension ext -> Language_extension.is_erasable ext + (* Builtin syntax changes don't involve additions or changes to concrete + syntax and are always erasable. + *) + | Builtin -> true +end (** Was this embedded as an [[%extension_node]] or an [[@attribute]]? Not exported. *) @@ -154,14 +166,76 @@ end (******************************************************************************) +module Misnamed_embedding_error = struct + type t = + | No_erasability + | No_feature + | Unknown_erasability of string + + let to_string = function + | No_erasability -> "Missing erasability and feature components" + | No_feature -> "Missing a feature component" + | Unknown_erasability str -> + Printf.sprintf + "Unrecognized component where erasability was expected: `%s'" + str +end + +(** The component of an attribute or extension name that identifies whether or + not the embedded syntax is *erasable*; that is, whether or not the + upstream OCaml compiler can safely interpret the AST while ignoring the + attribute or extension. (This means that syntax encoded as extension + nodes should always be non-erasable.) Tools that consume the parse tree + we generate can make use of this information; for instance, ocamlformat + will use it to guide how we present code that can be run with both our + compiler and the upstream compiler, and ppxlib can use it to decide + whether it's ok to allow ppxes to construct syntax that uses this + emedding. In particular, the upstream version of ppxlib will allow ppxes + to produce [[@jane.erasable.*]] attributes, but will report an error if a + ppx produces a [[@jane.non_erasable.*]] attribute. + + As mentioned above, unlike for attributes, the erasable/non-erasable + distinction is not meaningful for extension nodes, as the compiler will + always error if it sees an uninterpreted extension node. So, for purposes + of tools in the wider OCaml ecosystem, it is irrelevant whether embeddings + that use extension nodes indicate [Erasable] or [Non_erasable] for this + component, but the semantically correct choice and the one we've settled + on is to use [Non_erasable]. *) +module Erasability = struct + type t = + | Erasable + | Non_erasable + + let to_string = function + | Erasable -> "erasable" + | Non_erasable -> "non_erasable" + + let of_string = function + | "erasable" -> Ok Erasable + | "non_erasable" -> Ok Non_erasable + | _ -> Error () +end + (** An AST-style representation of the names used when generating extension nodes or attributes for modular syntax; see the .mli file for more details. *) module Embedded_name : sig - (** A nonempty list of name components, without the leading root component - that identifies it as part of the modular syntax mechanism; see the .mli - file for more details. *) - type t = ( :: ) of string * string list + + (** A nonempty list of name components, without the first two components. + (That is, without the leading root component that identifies it as part of + the modular syntax mechanism, and without the next component that + identifies the erasability.) See the .mli file for more details. *) + type components = ( :: ) of string * string list + + type t = + { erasability : Erasability.t + ; components : components + } + + (** See the mli. *) + val of_feature : Feature.t -> string list -> t + + val components : t -> components (** Convert one of these Jane syntax names to the embedded string form used in the OCaml AST as the name of an extension node or an attribute; not @@ -171,11 +245,12 @@ module Embedded_name : sig (** Parse a Jane syntax name from the OCaml AST, either as the name of an extension node or an attribute: - [Some (Ok _)] if it's a legal Jane-syntax name; - - [Some (Error ())] if it's the bare root name; and + - [Some (Error _)] if the root is present, but the name has fewer than 3 + components or the erasability component is malformed; and - [None] if it doesn't start with the leading root name and isn't part of our Jane-syntax machinery. Not exposed. *) - val of_string : string -> (t, unit) result option + val of_string : string -> (t, Misnamed_embedding_error.t) result option (** Print out the embedded form of a Jane-syntax name, in quotes; for use in error messages. *) @@ -185,11 +260,6 @@ module Embedded_name : sig accompanied by an indefinite article; for use in error messages. Not exposed. *) val pp_a_term : Format.formatter -> Embedding_syntax.t * t -> unit - - (** Print out the illegal empty quasi-Jane-syntax extension node or attribute - with no name beyond the leading root component; for use in error messages. - Not exposed. *) - val pp_bad_empty_term : Format.formatter -> Embedding_syntax.t -> unit end = struct (** The three parameters that control how we encode Jane-syntax extension node names. When updating these, update comments that refer to them by their @@ -207,18 +277,42 @@ end = struct end include Config + let separator_str = String.make 1 separator - type t = ( :: ) of string * string list + type components = ( :: ) of string * string list + + type t = + { erasability : Erasability.t + ; components : components + } + + let of_feature feature trailing_components = + let feature_component = Feature.extension_component feature in + let erasability : Erasability.t = + if Feature.is_erasable feature then Erasable else Non_erasable + in + { erasability; components = feature_component :: trailing_components } - let to_string (feat :: subparts) = - String.concat separator_str (root :: feat :: subparts) + let components t = t.components - let of_string str = match String.split_on_char separator str with + let to_string { erasability; components = feat :: subparts } = + String.concat + separator_str + (root :: Erasability.to_string erasability :: feat :: subparts) + + let of_string str : (t, Misnamed_embedding_error.t) result option = + match String.split_on_char separator str with | root' :: parts when String.equal root root' -> begin match parts with - | feat :: subparts -> Some (Ok (feat :: subparts)) - | [] -> Some (Error ()) + | [] -> Some (Error No_erasability) + | [_] -> Some (Error No_feature) + | erasability :: feat :: subparts -> begin + match Erasability.of_string erasability with + | Ok erasability -> + Some (Ok { erasability; components = feat :: subparts }) + | Error () -> Some (Error (Unknown_erasability erasability)) + end end | _ :: _ | [] -> None @@ -226,13 +320,11 @@ end = struct let pp_a_term ppf (esyn, t) = Format.fprintf ppf "%s %a" article Embedding_syntax.pp (esyn, to_string t) - - let pp_bad_empty_term ppf esyn = Embedding_syntax.pp ppf (esyn, root) end (******************************************************************************) module Error = struct - (** Someone used [[%jane.FEATNAME]]/[[@jane.FEATNAME]] wrong *) + (** Someone used [[%jane.*.FEATNAME]]/[[@jane.*.FEATNAME]] wrong *) type malformed_embedding = | Has_payload of payload @@ -241,10 +333,11 @@ module Error = struct type error = | Malformed_embedding of Embedding_syntax.t * Embedded_name.t * malformed_embedding - | Unknown_extension of Embedding_syntax.t * string + | Unknown_extension of Embedding_syntax.t * Erasability.t * string | Disabled_extension of Language_extension.t | Wrong_syntactic_category of Feature.t * string - | Unnamed_embedding of Embedding_syntax.t + | Misnamed_embedding of + Misnamed_embedding_error.t * string * Embedding_syntax.t | Bad_introduction of Embedding_syntax.t * Embedded_name.t (** The exception type thrown when desugaring a piece of modular syntax from @@ -270,12 +363,13 @@ let report_error ~loc = function (Embedding_syntax.name_plural what) Embedded_name.pp_quoted_name name end - | Unknown_extension (what, name) -> + | Unknown_extension (what, erasability, name) -> + let embedded_name = { Embedded_name.erasability; components = [name] } in Location.errorf ~loc "@[Unknown extension \"%s\" referenced via@ %a %s@]" name - Embedded_name.pp_a_term (what, Embedded_name.[name]) + Embedded_name.pp_a_term (what, embedded_name) (Embedding_syntax.name what) | Disabled_extension ext -> Location.errorf @@ -288,13 +382,14 @@ let report_error ~loc = function "%s cannot appear in %s" (Feature.describe_uppercase feat) cat - | Unnamed_embedding what -> + | Misnamed_embedding (err, name, what) -> Location.errorf ~loc - "Cannot have %s named %a" + "Cannot have %s named %a: %s" (Embedding_syntax.name_indefinite what) - Embedded_name.pp_bad_empty_term what - | Bad_introduction(what, (ext :: _ as name)) -> + Embedding_syntax.pp (what, name) + (Misnamed_embedding_error.to_string err) + | Bad_introduction(what, ({ components = ext :: _; _ } as name)) -> Location.errorf ~loc "@[The extension \"%s\" was referenced improperly; it started with@ \ @@ -302,7 +397,7 @@ let report_error ~loc = function ext Embedded_name.pp_a_term (what, name) (Embedding_syntax.name what) - Embedded_name.pp_a_term (what, Embedded_name.[ext]) + Embedded_name.pp_a_term (what, { name with components = [ext] }) let () = Location.register_error_of_exn @@ -315,9 +410,9 @@ let () = novel syntactic features. One module per variety of AST (expressions, patterns, etc.). *) -(** The parameters that define how to look for [[%jane.FEATNAME]] and - [[@jane.FEATNAME]] inside ASTs of a certain syntactic category. This module - type describes the input to the [Make_with_attribute] and +(** The parameters that define how to look for [[%jane.*.FEATNAME]] and + [[@jane.*.FEATNAME]] inside ASTs of a certain syntactic category. This + module type describes the input to the [Make_with_attribute] and [Make_with_extension_node] functors (though they stipulate additional requirements for their inputs). *) @@ -360,13 +455,6 @@ module type AST = sig val match_jane_syntax : ast -> (Embedded_name.t * ast) option end -(* Some extensions written before this file existed are handled in their own - way; this function filters them out. *) -let uniformly_handled_extension name = - match name with - | "local"|"global"|"nonlocal"|"escape"|"curry" -> false - | _ -> true - (* Parses the embedded name from an embedding, raising if the embedding is malformed. Malformed means either: @@ -378,8 +466,7 @@ let uniformly_handled_extension name = let parse_embedding_exn ~loc ~payload ~name ~embedding_syntax = let raise_error err = raise (Error (loc, err)) in match Embedded_name.of_string name with - | Some (Ok (feat :: _ as name)) - when uniformly_handled_extension feat -> begin + | Some (Ok name) -> begin let raise_malformed err = raise_error (Malformed_embedding (embedding_syntax, name, err)) in @@ -387,8 +474,9 @@ let parse_embedding_exn ~loc ~payload ~name ~embedding_syntax = | PStr [] -> Some name | _ -> raise_malformed (Has_payload payload) end - | Some (Error ()) -> raise_error (Unnamed_embedding embedding_syntax) - | Some (Ok (_ :: _)) | None -> None + | Some (Error err) -> + raise_error (Misnamed_embedding (err, name, embedding_syntax)) + | None -> None module With_attributes = struct type 'desc t = @@ -717,12 +805,20 @@ module AST = struct let (module AST) = to_module t in AST.wrap_desc - let make_jane_syntax (type ast ast_desc) (t : (ast, ast_desc) t) = + let make_jane_syntax + (type ast ast_desc) + (t : (ast, ast_desc) t) + feature + trailing_components + ast + = let (module AST) = to_module t in AST.make_jane_syntax + (Embedded_name.of_feature feature trailing_components) + ast - let make_entire_jane_syntax t ~loc name ast = - make_jane_syntax t [name] + let make_entire_jane_syntax t ~loc feature ast = + make_jane_syntax t feature [] (Ast_helper.with_default_loc (Location.ghostify loc) ast) (** Generically lift our custom ASTs for our novel syntax from OCaml ASTs. *) @@ -732,7 +828,7 @@ module AST = struct let loc = AST.location ast in let raise_error err = raise (Error (loc, err)) in match AST.match_jane_syntax ast with - | Some ([name], ast) -> begin + | Some ({ erasability; components = [name] }, ast) -> begin match Feature.of_component name with | Ok feat -> begin match of_ast_internal feat ast with @@ -743,10 +839,10 @@ module AST = struct | Error err -> raise_error begin match err with | Disabled_extension ext -> Disabled_extension ext | Unknown_extension name -> - Unknown_extension (AST.embedding_syntax, name) + Unknown_extension (AST.embedding_syntax, erasability, name) end end - | Some (_ :: _ :: _ as name, _) -> + | Some ({ components = _ :: _ :: _; _ } as name, _) -> raise_error (Bad_introduction(AST.embedding_syntax, name)) | None -> None in diff --git a/ocaml/parsing/jane_syntax_parsing.mli b/ocaml/parsing/jane_syntax_parsing.mli index 8f939ee0dff..5ca82ff25a5 100644 --- a/ocaml/parsing/jane_syntax_parsing.mli +++ b/ocaml/parsing/jane_syntax_parsing.mli @@ -96,6 +96,11 @@ module Feature : sig type t = | Language_extension of Language_extension.t | Builtin + + (** The component of an attribute or extension name that identifies the + feature. This is third component. + *) + val extension_component : t -> string end (** An AST-style representation of the names used when generating extension @@ -105,11 +110,27 @@ end also why we don't expose any functions for rendering or parsing these names; that's all handled internally. *) module Embedded_name : sig - (** A nonempty list of name components, without the leading root component - that identifies it as part of the modular syntax mechanism. This is a - nonempty list corresponding to the different components of the name: first - the feature, and then any subparts. *) - type t = ( :: ) of string * string list + + (** A nonempty list of name components, without the first two components. + (That is, without the leading root component that identifies it as part of + the modular syntax mechanism, and without the next component that + identifies the erasability.) + + This is a nonempty list corresponding to the different components of the + name: first the feature, and then any subparts. + *) + type components = ( :: ) of string * string list + + type t + + (** Creates an embedded name whose erasability component is whether the + feature is erasable, and whose feature component is the feature's name. + The second argument is treated as the trailing components after the + feature name. + *) + val of_feature : Feature.t -> string list -> t + + val components : t -> components (** Print out the embedded form of a Jane-syntax name, in quotes; for use in error messages. *) @@ -168,8 +189,12 @@ module AST : sig given name (the [Embedded_name.t]) and body (the [ast]). Any locations in the generated AST will be set to [!Ast_helper.default_loc], which should be [ghost]. *) - val make_jane_syntax : - ('ast, 'ast_desc) t -> Embedded_name.t -> 'ast -> 'ast_desc + val make_jane_syntax + : ('ast, 'ast_desc) t + -> Feature.t + -> string list + -> 'ast + -> 'ast_desc (** As [make_jane_syntax], but specifically for the AST node corresponding to the entire piece of novel syntax (e.g., for a list comprehension, the @@ -180,7 +205,7 @@ module AST : sig val make_entire_jane_syntax : ('ast, 'ast_desc) t -> loc:Location.t - -> string + -> Feature.t -> (unit -> 'ast) -> 'ast_desc @@ -239,8 +264,9 @@ val assert_extension_enabled : loc:Location.t -> Language_extension.t -> unit order to process a Jane Syntax element that consists of multiple nested ASTs. *) -val find_and_remove_jane_syntax_attribute : - Parsetree.attributes -> (Embedded_name.t * Parsetree.attributes) option +val find_and_remove_jane_syntax_attribute + : Parsetree.attributes + -> (Embedded_name.t * Parsetree.attributes) option (** Errors around the representation of our extended ASTs. These should mostly just be fatal, but they're needed for one test case diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error1.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error1.compilers.reference index 2e1ded53db9..30145e46aed 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error1.compilers.reference +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error1.compilers.reference @@ -1,5 +1,5 @@ -File "user_error1.ml", line 21, characters 44-58: -21 | let _malformed_extension_has_payload = () [@jane.something "no payloads"];; - ^^^^^^^^^^^^^^ +File "user_error1.ml", line 21, characters 44-67: +21 | let _malformed_extension_has_payload = () [@jane.erasable.something "no payloads"];; + ^^^^^^^^^^^^^^^^^^^^^^^ Error: Modular syntax attributes are not allowed to have a payload, - but "jane.something" does + but "jane.erasable.something" does diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error1.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error1.ml index 42a47335f62..27c5c550d66 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error1.ml +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error1.ml @@ -18,5 +18,5 @@ like it in separate files, because the "compile and test output" infrastructure reports only one error at a time. *) -let _malformed_extension_has_payload = () [@jane.something "no payloads"];; +let _malformed_extension_has_payload = () [@jane.erasable.something "no payloads"];; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error2.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error2.compilers.reference index 179d53c15e3..a94b0d0b93d 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error2.compilers.reference +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error2.compilers.reference @@ -1,4 +1,4 @@ -File "user_error2.ml", line 21, characters 46-60: -21 | let _malformed_extensions_wrong_arguments = [%jane.something] "two" "arguments";; - ^^^^^^^^^^^^^^ -Error: Uninterpreted extension 'jane.something'. +File "user_error2.ml", line 21, characters 46-69: +21 | let _malformed_extensions_wrong_arguments = [%jane.erasable.something] "two" "arguments";; + ^^^^^^^^^^^^^^^^^^^^^^^ +Error: Uninterpreted extension 'jane.erasable.something'. diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error2.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error2.ml index c09ca9743e1..805f5cd4ded 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error2.ml +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error2.ml @@ -18,4 +18,4 @@ like it in separate files, because the "compile and test output" infrastructure reports only one error at a time. *) -let _malformed_extensions_wrong_arguments = [%jane.something] "two" "arguments";; +let _malformed_extensions_wrong_arguments = [%jane.erasable.something] "two" "arguments";; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error3.compilers.reference index 6a01f3565b2..51ad08bf367 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error3.compilers.reference +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3.compilers.reference @@ -1,5 +1,5 @@ -File "user_error3.ml", line 21, characters 25-27: -21 | let _unknown_extension = () [@jane.this_extension_doesn't_exist];; - ^^ +File "user_error3.ml", line 21, characters 26-28: +21 | let _misnamed_extension = () [@jane.erasable.this_extension_doesn't_exist];; + ^^ Error: Unknown extension "this_extension_doesn't_exist" referenced via - a [@jane.this_extension_doesn't_exist] attribute + a [@jane.erasable.this_extension_doesn't_exist] attribute diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error3.ml index fc2584f2be3..a18058ccb60 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error3.ml +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3.ml @@ -18,4 +18,4 @@ like it in separate files, because the "compile and test output" infrastructure reports only one error at a time. *) -let _unknown_extension = () [@jane.this_extension_doesn't_exist];; +let _misnamed_extension = () [@jane.erasable.this_extension_doesn't_exist];; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.compilers.reference new file mode 100644 index 00000000000..1af2e3db578 --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.compilers.reference @@ -0,0 +1,4 @@ +File "user_error3_1.ml", line 9, characters 31-55: +9 | let _misnamed_extension = () [@jane.invalid_erasability];; + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot have an attribute named [@jane.invalid_erasability]: Missing a feature component diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.ml new file mode 100644 index 00000000000..4131439b873 --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_1.ml @@ -0,0 +1,9 @@ +(* TEST + ocamlc_byte_exit_status = "2" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + *** check-ocamlc.byte-output +*) + +(* See the comment in user_error3.ml *) +let _misnamed_extension = () [@jane.invalid_erasability];; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.compilers.reference new file mode 100644 index 00000000000..a7f73ce3c2a --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.compilers.reference @@ -0,0 +1,4 @@ +File "user_error3_2.ml", line 9, characters 31-48: +9 | let _misnamed_extension = () [@jane.non_erasable];; + ^^^^^^^^^^^^^^^^^ +Error: Cannot have an attribute named [@jane.non_erasable]: Missing a feature component diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.ml new file mode 100644 index 00000000000..9fdf36a3130 --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_2.ml @@ -0,0 +1,9 @@ +(* TEST + ocamlc_byte_exit_status = "2" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + *** check-ocamlc.byte-output +*) + +(* See the comment in user_error3.ml *) +let _misnamed_extension = () [@jane.non_erasable];; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.compilers.reference new file mode 100644 index 00000000000..ebb6d8a2768 --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.compilers.reference @@ -0,0 +1,4 @@ +File "user_error3_3.ml", line 9, characters 31-63: +9 | let _misnamed_extension = () [@jane.invalid_erasability.feature];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot have an attribute named [@jane.invalid_erasability.feature]: Unrecognized component where erasability was expected: `invalid_erasability' diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.ml new file mode 100644 index 00000000000..ffc73b28cc7 --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error3_3.ml @@ -0,0 +1,9 @@ +(* TEST + ocamlc_byte_exit_status = "2" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + *** check-ocamlc.byte-output +*) + +(* See the comment in user_error3.ml *) +let _misnamed_extension = () [@jane.invalid_erasability.feature];; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error4.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error4.compilers.reference index 5c872b45ae6..43e9aa05b7f 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error4.compilers.reference +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error4.compilers.reference @@ -1,4 +1,4 @@ File "user_error4.ml", line 21, characters 26-28: -21 | let _disabled_extension = () [@jane.comprehensions];; +21 | let _disabled_extension = () [@jane.non_erasable.comprehensions];; ^^ Error: The extension "comprehensions" is disabled and cannot be used diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error4.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error4.ml index 35c6fc15bb3..e5575810e9b 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error4.ml +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error4.ml @@ -18,4 +18,4 @@ like it in separate files, because the "compile and test output" infrastructure reports only one error at a time. *) -let _disabled_extension = () [@jane.comprehensions];; +let _disabled_extension = () [@jane.non_erasable.comprehensions];; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error5.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error5.compilers.reference index 3e2ea8644f0..e0d14e05f18 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error5.compilers.reference +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error5.compilers.reference @@ -1,4 +1,4 @@ File "user_error5.ml", line 21, characters 30-34: 21 | let _unnamed_extension = () [@jane];; ^^^^ -Error: Cannot have an attribute named [@jane] +Error: Cannot have an attribute named [@jane]: Missing erasability and feature components diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error6.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error6.compilers.reference index 2a37167d778..bc303263d3d 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error6.compilers.reference +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error6.compilers.reference @@ -1,5 +1,6 @@ File "user_error6.ml", line 21, characters 24-26: -21 | let _bad_introduction = () [@jane.something.nested];; +21 | let _bad_introduction = () [@jane.erasable.something.nested];; ^^ Error: The extension "something" was referenced improperly; it started with - a [@jane.something.nested] attribute, not a [@jane.something] one + a [@jane.erasable.something.nested] attribute, + not a [@jane.erasable.something] one diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error6.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error6.ml index 55ed4f58481..b126a93dd5e 100644 --- a/ocaml/testsuite/tests/jane-modular-syntax/user_error6.ml +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error6.ml @@ -18,4 +18,4 @@ like it in separate files, because the "compile and test output" infrastructure reports only one error at a time. *) -let _bad_introduction = () [@jane.something.nested];; +let _bad_introduction = () [@jane.erasable.something.nested];; diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.compilers.reference b/ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.compilers.reference new file mode 100644 index 00000000000..5e6e63df09e --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.compilers.reference @@ -0,0 +1,4 @@ +File "user_error7_attributes.ml", line 21, characters 5-9: +21 | let[@jane] f () = ();; + ^^^^ +Warning 53 [misplaced-attribute]: the "jane" attribute cannot appear in this context diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.ml new file mode 100644 index 00000000000..1f3c13e811e --- /dev/null +++ b/ocaml/testsuite/tests/jane-modular-syntax/user_error7_attributes.ml @@ -0,0 +1,25 @@ +(* TEST + + flags = "-w +A-60-70" + + * setup-ocamlc.byte-build-env + ** ocamlc.byte + compile_only = "true" + *** check-ocamlc.byte-output + +*) + +(* + If we use attributes on a syntactic category not handled by modular syntax, + they aren't interpreted by the modular syntax machinery and fail with a normal + OCaml error. + + We may some day run out of such syntactic categories, in which case we should + delete this test and leave a comment saying that we can't write such a test for + attributes because the modular syntax machinery always interprets them. +*) +let[@jane] f () = ();; + +(* We can't use expect test here because warning 53 is only raised by ocamlc, + not the toplevel. This is probably a bug. +*) diff --git a/ocaml/testsuite/tests/jane-modular-syntax/user_error7.ml b/ocaml/testsuite/tests/jane-modular-syntax/user_error7_extensions.ml similarity index 100% rename from ocaml/testsuite/tests/jane-modular-syntax/user_error7.ml rename to ocaml/testsuite/tests/jane-modular-syntax/user_error7_extensions.ml From c89b292f85f73b284f3757ed15eafe137b1c7fe1 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Mon, 20 Mar 2023 18:18:57 +0000 Subject: [PATCH 07/30] Unarization --- backend/cmm_helpers.ml | 14 +- backend/cmmgen.ml | 2 + middle_end/clambda_primitives.ml | 1 + middle_end/clambda_primitives.mli | 1 + middle_end/closure/closure.ml | 1 + middle_end/convert_primitives.ml | 2 + middle_end/flambda/closure_offsets.ml | 3 +- middle_end/flambda/flambda_to_clambda.ml | 3 +- .../bound_identifiers/bound_parameters.ml | 6 +- .../bound_identifiers/bound_parameters.mli | 2 +- .../from_lambda/closure_conversion.ml | 105 +- .../from_lambda/closure_conversion_aux.ml | 25 +- .../from_lambda/closure_conversion_aux.mli | 13 +- .../flambda2/from_lambda/lambda_to_flambda.ml | 900 ++++++++++++++---- .../lambda_to_flambda_primitives.ml | 3 +- middle_end/flambda2/kinds/flambda_arity.ml | 120 ++- middle_end/flambda2/kinds/flambda_arity.mli | 77 +- middle_end/flambda2/kinds/flambda_kind.ml | 2 + .../flambda2/parser/fexpr_to_flambda.ml | 19 +- .../flambda2/parser/flambda_to_fexpr.ml | 11 +- .../flambda2/simplify/apply_cont_rewrite.ml | 20 +- .../flambda2/simplify/apply_cont_rewrite.mli | 2 +- .../flambda2/simplify/continuation_in_env.ml | 6 +- .../flambda2/simplify/continuation_in_env.mli | 8 +- .../simplify/env/continuation_uses.ml | 14 +- .../simplify/env/continuation_uses.mli | 6 +- .../flambda2/simplify/env/upwards_env.mli | 11 +- middle_end/flambda2/simplify/expr_builder.ml | 21 +- middle_end/flambda2/simplify/expr_builder.mli | 4 +- middle_end/flambda2/simplify/flow/flow.mli | 2 +- middle_end/flambda2/simplify/flow/flow_acc.ml | 2 +- .../flambda2/simplify/flow/flow_acc.mli | 2 +- .../inlining/call_site_inlining_decision.ml | 5 +- .../inlining/call_site_inlining_decision.mli | 2 +- middle_end/flambda2/simplify/simplify.ml | 2 +- .../flambda2/simplify/simplify_apply_expr.ml | 106 ++- .../flambda2/simplify/simplify_common.ml | 38 +- .../flambda2/simplify/simplify_common.mli | 4 +- middle_end/flambda2/simplify/simplify_expr.ml | 2 +- .../simplify/simplify_set_of_closures.ml | 7 +- .../flambda2/simplify/simplify_switch_expr.ml | 8 +- .../simplify_shared/inlining_helpers.ml | 2 +- .../simplify_shared/inlining_helpers.mli | 2 +- .../flambda2/simplify_shared/slot_offsets.ml | 2 +- middle_end/flambda2/terms/apply_expr.ml | 8 +- middle_end/flambda2/terms/apply_expr.mli | 11 +- middle_end/flambda2/terms/code_metadata.ml | 20 +- middle_end/flambda2/terms/code_metadata.mli | 9 +- middle_end/flambda2/terms/exn_continuation.ml | 2 +- .../flambda2/terms/exn_continuation.mli | 2 +- middle_end/flambda2/to_cmm/to_cmm_env.ml | 2 +- middle_end/flambda2/to_cmm/to_cmm_env.mli | 2 +- middle_end/flambda2/to_cmm/to_cmm_expr.ml | 14 +- .../flambda2/to_cmm/to_cmm_set_of_closures.ml | 12 +- middle_end/flambda2/to_cmm/to_cmm_shared.ml | 5 +- middle_end/flambda2/to_cmm/to_cmm_shared.mli | 4 +- middle_end/flambda2/types/flambda2_types.mli | 6 +- .../types/grammar/more_type_creators.ml | 6 +- .../types/grammar/more_type_creators.mli | 6 +- middle_end/flambda2/ui/flambda_colours.ml | 2 + middle_end/flambda2/ui/flambda_colours.mli | 2 + middle_end/internal_variable_names.ml | 8 + middle_end/printclambda.ml | 1 + ocaml/asmcomp/cmm_helpers.ml | 2 +- ocaml/asmcomp/cmmgen.ml | 2 + ocaml/bytecomp/bytegen.ml | 2 + ocaml/lambda/lambda.ml | 16 +- ocaml/lambda/lambda.mli | 6 + ocaml/lambda/printlambda.ml | 27 +- ocaml/lambda/tmc.ml | 3 + ocaml/lambda/translprim.ml | 48 +- ocaml/middle_end/clambda_primitives.ml | 1 + ocaml/middle_end/clambda_primitives.mli | 1 + ocaml/middle_end/closure/closure.ml | 1 + ocaml/middle_end/convert_primitives.ml | 2 + ocaml/middle_end/flambda/closure_offsets.ml | 3 +- .../middle_end/flambda/flambda_to_clambda.ml | 3 +- ocaml/middle_end/internal_variable_names.ml | 8 + ocaml/middle_end/printclambda.ml | 1 + ocaml/typing/predef.ml | 6 + ocaml/typing/predef.mli | 3 + ocaml/typing/typeopt.ml | 8 +- ocaml/utils/misc.mli | 2 +- up.ml | 291 ++++++ 84 files changed, 1704 insertions(+), 442 deletions(-) create mode 100644 up.ml diff --git a/backend/cmm_helpers.ml b/backend/cmm_helpers.ml index ff688cfb23d..6e19bf909c5 100644 --- a/backend/cmm_helpers.ml +++ b/backend/cmm_helpers.ml @@ -1071,6 +1071,8 @@ module Extended_machtype = struct typ_any_int | Pvalue Pintval -> typ_tagged_int | Pvalue _ -> typ_val + | Punboxed_product _ -> + Misc.fatal_error "Punboxed_product not expected here" end let machtype_of_layout layout = @@ -4044,8 +4046,8 @@ let direct_call ~dbg ty pos f_code_sym args = Cop (Capply (ty, pos), f_code_sym :: args, dbg) let indirect_call ~dbg ty pos alloc_mode f args_type args = - match args with - | [arg] -> + match args_type with + | [_] -> (* Use a variable to avoid duplicating the cmm code of the closure [f]. *) let v = Backend_var.create_local "*closure*" in let v' = Backend_var.With_provenance.create v in @@ -4053,10 +4055,10 @@ let indirect_call ~dbg ty pos alloc_mode f args_type args = ~body: (Cop ( Capply (Extended_machtype.to_machtype ty, pos), - [load ~dbg Word_int Asttypes.Mutable ~addr:(Cvar v); arg; Cvar v], + (load ~dbg Word_int Asttypes.Mutable ~addr:(Cvar v) :: args) + @ [Cvar v], dbg )) - | args -> - call_caml_apply ty args_type Asttypes.Mutable f args pos alloc_mode dbg + | _ -> call_caml_apply ty args_type Asttypes.Mutable f args pos alloc_mode dbg let indirect_full_call ~dbg ty pos alloc_mode f args_type = function (* the single-argument case is already optimized by indirect_call *) @@ -4183,5 +4185,5 @@ let kind_of_layout (layout : Lambda.layout) = | Pvalue Pfloatval -> Boxed_float | Pvalue (Pboxedintval bi) -> Boxed_integer bi | Pvalue (Pgenval | Pintval | Pvariant _ | Parrayval _) - | Ptop | Pbottom | Punboxed_float | Punboxed_int _ -> + | Ptop | Pbottom | Punboxed_float | Punboxed_int _ | Punboxed_product _ -> Any diff --git a/backend/cmmgen.ml b/backend/cmmgen.ml index 5ff1b2f00d1..80106aead77 100644 --- a/backend/cmmgen.ml +++ b/backend/cmmgen.ml @@ -150,6 +150,7 @@ let get_field env layout ptr n dbg = | Pvalue Pintval | Punboxed_int _ -> Word_int | Pvalue _ -> Word_val | Punboxed_float -> Double + | Punboxed_product _ -> Misc.fatal_error "TBD" | Ptop -> Misc.fatal_errorf "get_field with Ptop: %a" Debuginfo.print_compact dbg | Pbottom -> @@ -1338,6 +1339,7 @@ and transl_let env str (layout : Lambda.layout) id exp transl_body = end | Pvalue kind -> transl_let_value env str kind id exp transl_body + | Punboxed_product _ -> Misc.fatal_error "TBD" and make_catch (kind : Cmm.kind_for_unboxing) ncatch body handler dbg = match body with diff --git a/middle_end/clambda_primitives.ml b/middle_end/clambda_primitives.ml index 77e66745305..b0b731993c7 100644 --- a/middle_end/clambda_primitives.ml +++ b/middle_end/clambda_primitives.ml @@ -150,6 +150,7 @@ and layout = Lambda.layout = | Pvalue of value_kind | Punboxed_float | Punboxed_int of boxed_integer + | Punboxed_product of layout list | Pbottom and block_shape = Lambda.block_shape diff --git a/middle_end/clambda_primitives.mli b/middle_end/clambda_primitives.mli index e71b17c4c85..5e3ddfd0765 100644 --- a/middle_end/clambda_primitives.mli +++ b/middle_end/clambda_primitives.mli @@ -153,6 +153,7 @@ and layout = Lambda.layout = | Pvalue of value_kind | Punboxed_float | Punboxed_int of boxed_integer + | Punboxed_product of layout list | Pbottom and block_shape = Lambda.block_shape diff --git a/middle_end/closure/closure.ml b/middle_end/closure/closure.ml index 87b13e0875b..1c2a1e2d26d 100644 --- a/middle_end/closure/closure.ml +++ b/middle_end/closure/closure.ml @@ -65,6 +65,7 @@ let is_gc_ignorable kind = | Punboxed_int _ -> true | Pvalue Pintval -> true | Pvalue (Pgenval | Pfloatval | Pboxedintval _ | Pvariant _ | Parrayval _) -> false + | Punboxed_product _ -> Misc.fatal_error "TBD" let split_closure_fv kinds fv = List.fold_right (fun id (not_scanned, scanned) -> diff --git a/middle_end/convert_primitives.ml b/middle_end/convert_primitives.ml index 541af7ecf86..9180f67f359 100644 --- a/middle_end/convert_primitives.ml +++ b/middle_end/convert_primitives.ml @@ -38,6 +38,8 @@ let convert (prim : Lambda.primitive) : Clambda_primitives.primitive = | Psetfloatfield (field, init_or_assign) -> Psetfloatfield (field, init_or_assign) | Pduprecord (repr, size) -> Pduprecord (repr, size) + | Pmake_unboxed_product _ + | Punboxed_product_field _ -> Misc.fatal_error "TODO" | Pccall prim -> Pccall prim | Praise kind -> Praise kind | Psequand -> Psequand diff --git a/middle_end/flambda/closure_offsets.ml b/middle_end/flambda/closure_offsets.ml index cfb1791786d..11f071656ec 100644 --- a/middle_end/flambda/closure_offsets.ml +++ b/middle_end/flambda/closure_offsets.ml @@ -80,7 +80,8 @@ let add_closure_offsets | Punboxed_float -> true | Punboxed_int _ -> true | Pvalue Pintval -> true - | Pvalue _ -> false) + | Pvalue _ -> false + | Punboxed_product _ -> Misc.fatal_error "TODO") free_vars in let free_variable_offsets, free_variable_pos = diff --git a/middle_end/flambda/flambda_to_clambda.ml b/middle_end/flambda/flambda_to_clambda.ml index 7e25f986854..a5be4f92237 100644 --- a/middle_end/flambda/flambda_to_clambda.ml +++ b/middle_end/flambda/flambda_to_clambda.ml @@ -713,7 +713,8 @@ and to_clambda_set_of_closures t env | Punboxed_float -> true | Punboxed_int _ -> true | Pvalue Pintval -> true - | Pvalue _ -> false) + | Pvalue _ -> false + | Punboxed_product _ -> Misc.fatal_error "TBD") free_vars in let to_closure_args free_vars = diff --git a/middle_end/flambda2/bound_identifiers/bound_parameters.ml b/middle_end/flambda2/bound_identifiers/bound_parameters.ml index 99498cc3d07..9cc4bb1d2ed 100644 --- a/middle_end/flambda2/bound_identifiers/bound_parameters.ml +++ b/middle_end/flambda2/bound_identifiers/bound_parameters.ml @@ -58,7 +58,11 @@ let var_set t = Variable.Set.of_list (vars t) let rename t = List.map (fun t -> BP.rename t) t -let arity t = List.map (fun t -> BP.kind t) t |> Flambda_arity.create +let arity t = + List.map + (fun t -> Flambda_arity.Component_for_creation.Singleton (BP.kind t)) + t + |> Flambda_arity.create let free_names t = List.fold_left diff --git a/middle_end/flambda2/bound_identifiers/bound_parameters.mli b/middle_end/flambda2/bound_identifiers/bound_parameters.mli index 82460e86e9a..418078cf20d 100644 --- a/middle_end/flambda2/bound_identifiers/bound_parameters.mli +++ b/middle_end/flambda2/bound_identifiers/bound_parameters.mli @@ -30,7 +30,7 @@ val is_empty : t -> bool val same_number : t -> t -> bool -val arity : t -> Flambda_arity.t +val arity : t -> [> `Unarized] Flambda_arity.t val check_no_duplicates : t -> unit diff --git a/middle_end/flambda2/from_lambda/closure_conversion.ml b/middle_end/flambda2/from_lambda/closure_conversion.ml index d7912d3685d..f9471694714 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion.ml @@ -238,7 +238,7 @@ module Inlining = struct | Some (Closure_approximation { code; _ }) -> let metadata = Code_or_metadata.code_metadata code in let fun_params_length = - Code_metadata.params_arity metadata |> Flambda_arity.cardinal + Code_metadata.params_arity metadata |> Flambda_arity.num_params in if (not (Code_or_metadata.code_present code)) || fun_params_length > List.length (Apply_expr.args apply) @@ -440,11 +440,11 @@ let close_c_call acc env ~loc ~let_bound_var let param_arity = List.map kind_of_primitive_native_repr prim_native_repr_args |> List.map K.With_subkind.anything - |> Flambda_arity.create + |> Flambda_arity.create_singletons in let return_kind = kind_of_primitive_native_repr prim_native_repr_res in let return_arity = - Flambda_arity.create [K.With_subkind.anything return_kind] + Flambda_arity.create_singletons [K.With_subkind.anything return_kind] in let call_kind = Call_kind.c_call ~alloc:prim_alloc ~is_c_builtin:prim_c_builtin @@ -704,7 +704,7 @@ let close_primitive acc env ~let_bound_var named (prim : Lambda.primitive) ~args | Pbigstring_set_64 _ | Pctconst _ | Pbswap16 | Pbbswap _ | Pint_as_pointer | Popaque _ | Pprobe_is_enabled _ | Pobj_dup | Pobj_magic _ | Punbox_float | Pbox_float _ | Punbox_int _ | Pbox_int _ - -> + | Pmake_unboxed_product _ | Punboxed_product_field _ -> (* Inconsistent with outer match *) assert false in @@ -1058,6 +1058,7 @@ let close_exact_or_unknown_apply acc env mode; region_close; region; + args_arity; return_arity } : IR.apply) callee_approx ~replace_region : Expr_with_acc.t = @@ -1101,7 +1102,7 @@ let close_exact_or_unknown_apply acc env close_exn_continuation acc env exn_continuation in let acc, args_with_arity = find_simples_and_arity acc env args in - let args, args_arity = List.split args_with_arity in + let args, _split_args_arity = List.split args_with_arity in let inlined_call = Inlined_attribute.from_lambda inlined in let probe = Probe.from_lambda probe in let position = @@ -1111,9 +1112,9 @@ let close_exact_or_unknown_apply acc env in let apply = Apply.create ~callee ~continuation:(Return continuation) - apply_exn_continuation ~args - ~args_arity:(Flambda_arity.create args_arity) - ~return_arity ~call_kind + apply_exn_continuation ~args ~args_arity + ~return_arity:(Flambda_arity.unarize_t return_arity) + ~call_kind (Debuginfo.from_location loc) ~inlined:inlined_call ~inlining_state:(Inlining_state.default ~round:0) @@ -1519,7 +1520,7 @@ let close_one_function acc ~code_id ~external_env ~by_function_slot decl (Exn_continuation.exn_handler exn_continuation) in let closure_info, acc = Acc.pop_closure_info acc in - let params_arity = Bound_parameters.arity params in + let params_arity = Function_decl.params_arity decl in let is_tupled = match Function_decl.kind decl with Curried _ -> false | Tupled -> true in @@ -1651,7 +1652,8 @@ let close_functions acc external_env ~current_region function_declarations = let code_id = Function_slot.Map.find function_slot function_code_ids in let params = Function_decl.params decl in let params_arity = - List.map (fun (_, kind) -> kind) params |> Flambda_arity.create + List.map (fun (_, kind) -> kind) params + |> Flambda_arity.create_singletons in let result_arity = Function_decl.return decl in let poll_attribute = @@ -1969,8 +1971,18 @@ let wrap_partial_application acc env apply_continuation (apply : IR.apply) (fun n kind_with_subkind -> ( Ident.create_local ("param" ^ string_of_int (num_provided + n)), kind_with_subkind )) - (Flambda_arity.to_list missing_arity) - in + (Flambda_arity.unarize missing_arity) + in + let params_arity = missing_arity in + (match Sys.getenv "DEBUG" with + | exception Not_found -> () + | _ -> + Format.eprintf + "partial application (in CC) of %a: old params arity is %a, new params \ + arity is %a\n\ + %!" + Ident.print apply.func Flambda_arity.print arity Flambda_arity.print + params_arity); let return_continuation = Continuation.create ~sort:Return () in let exn_continuation = IR.{ exn_handler = Continuation.create (); extra_args = [] } @@ -1986,6 +1998,7 @@ let wrap_partial_application acc env apply_continuation (apply : IR.apply) { apply with kind = Function; args = all_args; + args_arity = arity; continuation = return_continuation; exn_continuation; inlined = Lambda.Default_inlined; @@ -2016,7 +2029,10 @@ let wrap_partial_application acc env apply_continuation (apply : IR.apply) in let closure_alloc_mode, num_trailing_local_params = let num_leading_heap_params = - Flambda_arity.cardinal arity - num_trailing_local_params + (* This is a pre-unarization calculation so uses [num_params] not + [cardinal_unarized]. *) + (* CR mshinwell: check this is correct *) + Flambda_arity.num_params arity - num_trailing_local_params in if num_provided <= num_leading_heap_params then Lambda.alloc_heap, num_trailing_local_params @@ -2032,11 +2048,11 @@ let wrap_partial_application acc env apply_continuation (apply : IR.apply) let function_declarations = [ Function_decl.create ~let_rec_ident:(Some wrapper_id) ~function_slot ~kind:(Lambda.Curried { nlocal = num_trailing_local_params }) - ~params ~return:apply.return_arity ~return_continuation - ~exn_continuation ~my_region:apply.region ~body:fbody ~attr - ~loc:apply.loc ~free_idents_of_body ~closure_alloc_mode - ~num_trailing_local_params ~contains_no_escaping_local_allocs - Recursive.Non_recursive ] + ~params ~params_arity ~removed_params:Ident.Set.empty + ~return:apply.return_arity ~return_continuation ~exn_continuation + ~my_region:apply.region ~body:fbody ~attr ~loc:apply.loc + ~free_idents_of_body ~closure_alloc_mode ~num_trailing_local_params + ~contains_no_escaping_local_allocs Recursive.Non_recursive ] in let body acc env = let arg = find_simple_from_id env wrapper_id in @@ -2052,6 +2068,13 @@ let wrap_partial_application acc env apply_continuation (apply : IR.apply) let wrap_over_application acc env full_call (apply : IR.apply) ~remaining ~remaining_arity ~contains_no_escaping_local_allocs = + (* Format.eprintf "wrap_over_application of %a, args %a, args_arity(apply)=%a, + \ result_arity(apply)=%a@ remaining=(%a)@ remaining_arity=%a\n\ %!" + Ident.print apply.func (Format.pp_print_list ~pp_sep:Format.pp_print_space + IR.print_simple) apply.args (Misc.Stdlib.Option.print Flambda_arity.print) + apply.args_arity Flambda_arity.print apply.return_arity + (Format.pp_print_list ~pp_sep:Format.pp_print_space IR.print_simple) + remaining Flambda_arity.print remaining_arity; *) let wrapper_cont = Continuation.create () in let returned_func = Variable.create "func" in (* See comments in [Simplify_common.split_direct_over_application] about this @@ -2097,7 +2120,8 @@ let wrap_over_application acc env full_call (apply : IR.apply) ~remaining let over_application = Apply.create ~callee:(Simple.var returned_func) ~continuation apply_exn_continuation ~args:remaining ~args_arity:remaining_arity - ~return_arity:apply.return_arity ~call_kind apply_dbg ~inlined + ~return_arity:(Flambda_arity.unarize_t apply.return_arity) + ~call_kind apply_dbg ~inlined ~inlining_state:(Inlining_state.default ~round:0) ~probe ~position ~relative_history:(Env.relative_history_from_scoped ~loc:apply.loc env) @@ -2110,7 +2134,7 @@ let wrap_over_application acc env full_call (apply : IR.apply) ~remaining List.mapi (fun i kind -> BP.create (Variable.create ("result" ^ string_of_int i)) kind) - (Flambda_arity.to_list apply.return_arity) + (Flambda_arity.unarize apply.return_arity) in let handler acc = let acc, call_return_continuation = @@ -2153,12 +2177,13 @@ type call_args_split = | Exact of IR.simple list | Partial_app of { provided : IR.simple list; - missing_arity : Flambda_arity.t + missing_arity : [`Unarized | `Complex] Flambda_arity.t } | Over_app of { full : IR.simple list; + provided_arity : [`Unarized | `Complex] Flambda_arity.t; remaining : IR.simple list; - remaining_arity : Flambda_arity.t + remaining_arity : [`Unarized | `Complex] Flambda_arity.t } let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = @@ -2190,10 +2215,10 @@ let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = is_tupled, num_trailing_local_params, contains_no_escaping_local_allocs ) -> ( - let acc, args_with_arities = find_simples_and_arity acc env apply.args in - let args_arity = List.map snd args_with_arities in + let acc, _ = find_simples_and_arity acc env apply.args in let split_args = - let arity = Flambda_arity.to_list arity in + let non_unarized_arity = arity in + let arity = Flambda_arity.unarize arity in let split args arity = let rec cut n l = if n <= 0 @@ -2205,24 +2230,28 @@ let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = let before, after = cut (n - 1) t in h :: before, after in - let args_l = List.length args in - let arity_l = List.length arity in + let args_l = Flambda_arity.num_params apply.args_arity in + let arity_l = Flambda_arity.num_params non_unarized_arity in if args_l = arity_l then Exact args else if args_l < arity_l then - let _provided_arity, missing_arity = cut args_l arity in - Partial_app - { provided = args; - missing_arity = Flambda_arity.create missing_arity - } + let missing_arity = + Flambda_arity.partially_apply non_unarized_arity + ~num_non_unarized_params_provided:args_l + in + Partial_app { provided = args; missing_arity } else - let full, remaining = cut arity_l args in - let _, remaining_arity = cut arity_l args_arity in + let full, remaining = cut (List.length arity) args in + let remaining_arity = + Flambda_arity.partially_apply apply.args_arity + ~num_non_unarized_params_provided:arity_l + in Over_app { full; + provided_arity = non_unarized_arity; remaining; - remaining_arity = Flambda_arity.create remaining_arity + remaining_arity } in let arity = @@ -2249,7 +2278,7 @@ let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = wrap_partial_application acc env apply.continuation apply approx ~provided ~missing_arity ~arity ~num_trailing_local_params ~contains_no_escaping_local_allocs - | Over_app { full; remaining; remaining_arity } -> + | Over_app { full; provided_arity; remaining; remaining_arity } -> let full_args_call apply_continuation ~region acc = let mode = if contains_no_escaping_local_allocs @@ -2259,10 +2288,12 @@ let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = close_exact_or_unknown_apply acc env { apply with args = full; + args_arity = provided_arity; continuation = apply_continuation; mode; return_arity = - Flambda_arity.create [Flambda_kind.With_subkind.any_value] + Flambda_arity.create_singletons + [Flambda_kind.With_subkind.any_value] } (Some approx) ~replace_region:(Some region) in diff --git a/middle_end/flambda2/from_lambda/closure_conversion_aux.ml b/middle_end/flambda2/from_lambda/closure_conversion_aux.ml index f83b17f87ae..c8a678dd818 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion_aux.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion_aux.ml @@ -64,7 +64,8 @@ module IR = struct probe : Lambda.probe; mode : Lambda.alloc_mode; region : Ident.t; - return_arity : Flambda_arity.t + args_arity : [`Unarized | `Complex] Flambda_arity.t; + return_arity : [`Unarized | `Complex] Flambda_arity.t } type switch = @@ -674,7 +675,9 @@ module Function_decls = struct function_slot : Function_slot.t; kind : Lambda.function_kind; params : (Ident.t * Flambda_kind.With_subkind.t) list; - return : Flambda_arity.t; + removed_params : Ident.Set.t; + params_arity : [`Unarized | `Complex] Flambda_arity.t; + return : [`Unarized | `Complex] Flambda_arity.t; return_continuation : Continuation.t; exn_continuation : IR.exn_continuation; my_region : Ident.t; @@ -688,11 +691,11 @@ module Function_decls = struct contains_no_escaping_local_allocs : bool } - let create ~let_rec_ident ~function_slot ~kind ~params ~return - ~return_continuation ~exn_continuation ~my_region ~body - ~(attr : Lambda.function_attribute) ~loc ~free_idents_of_body recursive - ~closure_alloc_mode ~num_trailing_local_params - ~contains_no_escaping_local_allocs = + let create ~let_rec_ident ~function_slot ~kind ~params ~params_arity + ~removed_params ~return ~return_continuation ~exn_continuation + ~my_region ~body ~(attr : Lambda.function_attribute) ~loc + ~free_idents_of_body recursive ~closure_alloc_mode + ~num_trailing_local_params ~contains_no_escaping_local_allocs = let let_rec_ident = match let_rec_ident with | None -> Ident.create_local "unnamed_function" @@ -702,6 +705,8 @@ module Function_decls = struct function_slot; kind; params; + params_arity; + removed_params; return; return_continuation; exn_continuation; @@ -724,6 +729,8 @@ module Function_decls = struct let params t = t.params + let params_arity t = t.params_arity + let return t = t.return let return_continuation t = t.return_continuation @@ -734,7 +741,7 @@ module Function_decls = struct let body t = t.body - let free_idents t = t.free_idents_of_body + let free_idents t = Ident.Set.diff t.free_idents_of_body t.removed_params let inline t = t.attr.inline @@ -940,7 +947,7 @@ module Let_with_acc = struct ~find_code_characteristics:(fun code_id -> let code = Code_id.Map.find code_id code_mapping in { cost_metrics = Code.cost_metrics code; - params_arity = Flambda_arity.cardinal (Code.params_arity code) + params_arity = Flambda_arity.num_params (Code.params_arity code) }) set_of_closures | Rec_info _ -> Cost_metrics.zero diff --git a/middle_end/flambda2/from_lambda/closure_conversion_aux.mli b/middle_end/flambda2/from_lambda/closure_conversion_aux.mli index 1d32232d514..cd8e16232fa 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion_aux.mli +++ b/middle_end/flambda2/from_lambda/closure_conversion_aux.mli @@ -68,7 +68,8 @@ module IR : sig probe : Lambda.probe; mode : Lambda.alloc_mode; region : Ident.t; - return_arity : Flambda_arity.t + args_arity : [`Unarized | `Complex] Flambda_arity.t; + return_arity : [`Unarized | `Complex] Flambda_arity.t } type switch = @@ -77,6 +78,8 @@ module IR : sig failaction : (Continuation.t * trap_action option * simple list) option } + val print_simple : Format.formatter -> simple -> unit + val print_named : Format.formatter -> named -> unit end @@ -298,7 +301,9 @@ module Function_decls : sig function_slot:Function_slot.t -> kind:Lambda.function_kind -> params:(Ident.t * Flambda_kind.With_subkind.t) list -> - return:Flambda_arity.t -> + params_arity:[`Unarized | `Complex] Flambda_arity.t -> + removed_params:Ident.Set.t -> + return:[`Unarized | `Complex] Flambda_arity.t -> return_continuation:Continuation.t -> exn_continuation:IR.exn_continuation -> my_region:Ident.t -> @@ -320,7 +325,9 @@ module Function_decls : sig val params : t -> (Ident.t * Flambda_kind.With_subkind.t) list - val return : t -> Flambda_arity.t + val params_arity : t -> [`Unarized | `Complex] Flambda_arity.t + + val return : t -> [`Unarized | `Complex] Flambda_arity.t val return_continuation : t -> Continuation.t diff --git a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml index d42babe85ad..0320cd1c3a5 100644 --- a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml +++ b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml @@ -17,6 +17,9 @@ (* "Use CPS". -- A. Kennedy, "Compiling with Continuations Continued", ICFP 2007. *) +let unboxed_product_debug () = + match Sys.getenv "DEBUG" with exception Not_found -> false | _ -> true + module L = Lambda module CC = Closure_conversion module P = Flambda_primitive @@ -44,14 +47,30 @@ module Env : sig val is_mutable : t -> Ident.t -> bool - val register_mutable_variable : t -> Ident.t -> Lambda.layout -> t * Ident.t + val register_mutable_variable : + t -> Ident.t -> Flambda_kind.With_subkind.t -> t * Ident.t val update_mutable_variable : t -> Ident.t -> t * Ident.t + val register_unboxed_product : + t -> + unboxed_product:Ident.t -> + before_unarization: + [`Unarized | `Complex] Flambda_arity.Component_for_creation.t -> + fields:(Ident.t * Flambda_kind.With_subkind.t) list -> + t + + val get_unboxed_product_fields : + t -> + Ident.t -> + ([`Unarized | `Complex] Flambda_arity.Component_for_creation.t + * Ident.t list) + option + type add_continuation_result = private { body_env : t; handler_env : t; - extra_params : (Ident.t * Lambda.layout) list + extra_params : (Ident.t * Flambda_kind.With_subkind.t) list } val add_continuation : @@ -77,11 +96,10 @@ module Env : sig val extra_args_for_continuation : t -> Continuation.t -> Ident.t list val extra_args_for_continuation_with_kinds : - t -> Continuation.t -> (Ident.t * Lambda.layout) list - - val get_mutable_variable : t -> Ident.t -> Ident.t + t -> Continuation.t -> (Ident.t * Flambda_kind.With_subkind.t) list - val get_mutable_variable_with_kind : t -> Ident.t -> Ident.t * Lambda.layout + val get_mutable_variable_with_kind : + t -> Ident.t -> Ident.t * Flambda_kind.With_subkind.t (** About local allocation regions: @@ -186,8 +204,14 @@ end = struct type t = { current_unit : Compilation_unit.t; current_values_of_mutables_in_scope : - (Ident.t * Lambda.layout) Ident.Map.t; + (Ident.t * Flambda_kind.With_subkind.t) Ident.Map.t; mutables_needed_by_continuations : Ident.Set.t Continuation.Map.t; + unboxed_product_components_in_scope : + ([`Unarized | `Complex] Flambda_arity.Component_for_creation.t + * (Ident.t * Flambda_kind.With_subkind.t) array) + Ident.Map.t; + unboxed_product_components_needed_by_continuations : + Ident.Set.t Continuation.Map.t; try_stack : Continuation.t list; try_stack_at_handler : Continuation.t list Continuation.Map.t; static_exn_continuation : Continuation.t Numeric_types.Int.Map.t; @@ -203,9 +227,15 @@ end = struct Continuation.Map.of_list [return_continuation, Ident.Set.empty; exn_continuation, Ident.Set.empty] in + let unboxed_product_components_needed_by_continuations = + Continuation.Map.of_list + [return_continuation, Ident.Set.empty; exn_continuation, Ident.Set.empty] + in { current_unit; current_values_of_mutables_in_scope = Ident.Map.empty; mutables_needed_by_continuations; + unboxed_product_components_in_scope = Ident.Map.empty; + unboxed_product_components_needed_by_continuations; try_stack = []; try_stack_at_handler = Continuation.Map.empty; static_exn_continuation = Numeric_types.Int.Map.empty; @@ -245,10 +275,30 @@ end = struct let mutables_in_scope t = Ident.Map.keys t.current_values_of_mutables_in_scope + let register_unboxed_product t ~unboxed_product ~before_unarization ~fields = + if unboxed_product_debug () + then + Format.eprintf "register_unboxed_product %a: fields: %a\n%!" Ident.print + unboxed_product + (Format.pp_print_list ~pp_sep:Format.pp_print_space + (fun ppf (id, kind) -> + Format.fprintf ppf "%a :: %a" Ident.print id + Flambda_kind.With_subkind.print kind)) + fields; + { t with + unboxed_product_components_in_scope = + Ident.Map.add unboxed_product + (before_unarization, Array.of_list fields) + t.unboxed_product_components_in_scope + } + + let unboxed_product_components_in_scope t = + Ident.Map.keys t.unboxed_product_components_in_scope + type add_continuation_result = { body_env : t; handler_env : t; - extra_params : (Ident.t * Lambda.layout) list + extra_params : (Ident.t * Flambda_kind.With_subkind.t) list } let add_continuation t cont ~push_to_try_stack (recursive : Asttypes.rec_flag) @@ -261,11 +311,17 @@ end = struct Continuation.Map.add cont (mutables_in_scope t) t.mutables_needed_by_continuations in + let unboxed_product_components_needed_by_continuations = + Continuation.Map.add cont + (unboxed_product_components_in_scope t) + t.unboxed_product_components_needed_by_continuations + in let try_stack = if push_to_try_stack then cont :: t.try_stack else t.try_stack in { t with mutables_needed_by_continuations; + unboxed_product_components_needed_by_continuations; try_stack; region_stack_in_cont_scope } @@ -275,6 +331,15 @@ end = struct (fun mut_var (_outer_value, kind) -> Ident.rename mut_var, kind) t.current_values_of_mutables_in_scope in + let unboxed_product_components_in_scope = + Ident.Map.map + (fun (before_unarization, fields) -> + let fields = + Array.map (fun (field, layout) -> Ident.rename field, layout) fields + in + before_unarization, fields) + t.unboxed_product_components_in_scope + in let handler_env = let handler_env = match recursive with @@ -286,12 +351,24 @@ end = struct in { handler_env with current_values_of_mutables_in_scope; + unboxed_product_components_in_scope; region_stack_in_cont_scope } in + let extra_params_for_unboxed_products = + Ident.Map.data handler_env.unboxed_product_components_in_scope + |> List.map snd |> List.map Array.to_list |> List.concat + in let extra_params = Ident.Map.data handler_env.current_values_of_mutables_in_scope + @ extra_params_for_unboxed_products in + if unboxed_product_debug () + then + Format.eprintf "Adding continuation %a with extra params: %a\n%!" + Continuation.print cont + (Format.pp_print_list ~pp_sep:Format.pp_print_space Ident.print) + (List.map fst extra_params); { body_env; handler_env; extra_params } let add_static_exn_continuation t static_exn cont = @@ -343,18 +420,48 @@ end = struct | stack -> stack let extra_args_for_continuation_with_kinds t cont = - match Continuation.Map.find cont t.mutables_needed_by_continuations with - | exception Not_found -> - Misc.fatal_errorf "Unbound continuation %a" Continuation.print cont - | mutables -> - let mutables = Ident.Set.elements mutables in - List.map - (fun mut -> - match Ident.Map.find mut t.current_values_of_mutables_in_scope with - | exception Not_found -> - Misc.fatal_errorf "No current value for %a" Ident.print mut - | current_value, kind -> current_value, kind) - mutables + let for_mutables = + match Continuation.Map.find cont t.mutables_needed_by_continuations with + | exception Not_found -> + Misc.fatal_errorf "Unbound continuation %a" Continuation.print cont + | mutables -> + let mutables = Ident.Set.elements mutables in + List.map + (fun mut -> + match Ident.Map.find mut t.current_values_of_mutables_in_scope with + | exception Not_found -> + Misc.fatal_errorf "No current value for %a" Ident.print mut + | current_value, kind -> current_value, kind) + mutables + in + let for_unboxed_products = + match + Continuation.Map.find cont + t.unboxed_product_components_needed_by_continuations + with + | exception Not_found -> + Misc.fatal_errorf "Unbound continuation %a" Continuation.print cont + | unboxed_products_to_fields -> + let unboxed_products = Ident.Set.elements unboxed_products_to_fields in + List.concat_map + (fun unboxed_product -> + match + Ident.Map.find unboxed_product + t.unboxed_product_components_in_scope + with + | exception Not_found -> + Misc.fatal_errorf + "No field list registered for unboxed product %a" Ident.print + unboxed_product + | _, fields -> Array.to_list fields) + unboxed_products + in + if unboxed_product_debug () + then + Format.eprintf "Extra args for %a are: %a\n%!" Continuation.print cont + (Format.pp_print_list ~pp_sep:Format.pp_print_space Ident.print) + (List.map fst (for_mutables @ for_unboxed_products)); + for_mutables @ for_unboxed_products let extra_args_for_continuation t cont = List.map fst (extra_args_for_continuation_with_kinds t cont) @@ -365,7 +472,11 @@ end = struct Misc.fatal_errorf "Mutable variable %a not bound in env" Ident.print id | id, kind -> id, kind - let get_mutable_variable t id = fst (get_mutable_variable_with_kind t id) + let get_unboxed_product_fields t id = + match Ident.Map.find id t.unboxed_product_components_in_scope with + | exception Not_found -> None + | before_unarization, fields -> + Some (before_unarization, List.map fst (Array.to_list fields)) let entering_region t id ~continuation_closing_region ~continuation_after_closing_region = @@ -457,6 +568,18 @@ module Acc = Closure_conversion_aux.Acc type primitive_transform_result = | Primitive of L.primitive * L.lambda list * L.scoped_location | Transformed of L.lambda + | Unboxed_binding of + (Ident.t * Flambda_kind.With_subkind.t) option list * Env.t + (** [Unboxed_binding] enables a subset of the unboxed values arriving from + the defining expression to be bound. *) + +let must_be_singleton_simple simples = + match simples with + | [simple] -> simple + | [] | _ :: _ -> + Misc.fatal_errorf "Expected singleton Simple but got: %a" + (Format.pp_print_list ~pp_sep:Format.pp_print_space IR.print_simple) + simples let print_compact_location ppf (loc : Location.t) = if loc.loc_start.pos_fname = "//toplevel//" @@ -475,13 +598,9 @@ let name_for_function (func : Lambda.lfunction) = Format.asprintf "anon-fn[%a]" print_compact_location loc let extra_args_for_exn_continuation env exn_handler = - let more_extra_args = - Env.extra_args_for_continuation_with_kinds env exn_handler - in List.map - (fun (arg, kind) : (IR.simple * _) -> - Var arg, Flambda_kind.With_subkind.from_lambda kind) - more_extra_args + (fun (ident, kind) -> IR.Var ident, kind) + (Env.extra_args_for_continuation_with_kinds env exn_handler) let _print_stack ppf stack = Format.fprintf ppf "%a" @@ -599,7 +718,7 @@ let switch_for_if_then_else ~cond ~ifso ~ifnot ~kind = in L.Lswitch (cond, switch, Loc_unknown, kind) -let transform_primitive env (prim : L.primitive) args loc = +let transform_primitive env id (prim : L.primitive) args loc = match prim, args with | Psequor, [arg1; arg2] -> let const_true = Ident.create_local "const_true" in @@ -699,9 +818,120 @@ let transform_primitive env (prim : L.primitive) args loc = Primitive (L.Pccall desc, args, loc) else Misc.fatal_errorf - "Lambda_to_flambda.transform_primimive: Pbigarrayset with unknown \ + "Lambda_to_flambda.transform_primitive: Pbigarrayset with unknown \ layout and elements should only have dimensions between 1 and 3 \ (see translprim).") + | Pmake_unboxed_product layouts, args -> + (* CR mshinwell: should there be a case here for when args is a + singleton? *) + if List.compare_lengths layouts args <> 0 + then + Misc.fatal_errorf + "Pmake_unboxed_product layouts (%a) don't match arguments (%a)" + (Format.pp_print_list ~pp_sep:Format.pp_print_space Printlambda.layout) + layouts + (Format.pp_print_list ~pp_sep:Format.pp_print_space Printlambda.lambda) + args; + let arity_component = + Flambda_arity.Component_for_creation.Unboxed_product + (List.map Flambda_arity.Component_for_creation.from_lambda layouts) + in + let arity = Flambda_arity.create [arity_component] in + let fields = Flambda_arity.fresh_idents_unarized ~id arity in + let env = + Env.register_unboxed_product env ~unboxed_product:id + ~before_unarization:arity_component ~fields + in + if unboxed_product_debug () + then + Format.eprintf "Making unboxed product, bound to %a: num fields = %d\n%!" + Ident.print id (List.length fields); + let fields = List.map (fun ident_and_kind -> Some ident_and_kind) fields in + Unboxed_binding (fields, env) + | Punboxed_product_field (n, layouts), [_arg] -> + let layouts_array = Array.of_list layouts in + if n < 0 || n >= Array.length layouts_array + then Misc.fatal_errorf "Invalid field index %d for Punboxed_product_field" n; + let arity_component = + Flambda_arity.Component_for_creation.Unboxed_product + (List.map Flambda_arity.Component_for_creation.from_lambda layouts) + in + let arity = Flambda_arity.create [arity_component] in + if unboxed_product_debug () + then + Format.eprintf + "Punboxed_product_field bound to %a, product %a, field %d, arity %a:\n\ + %!" + Ident.print id Printlambda.lambda _arg n Flambda_arity.print arity; + let field_arity_component = + (* N.B. The arity of the field being projected, bound to [id], may in + itself be an unboxed product. *) + layouts_array.(n) |> Flambda_arity.Component_for_creation.from_lambda + in + let field_arity = Flambda_arity.create [field_arity_component] in + let ids_all_fields_with_kinds = + Flambda_arity.fresh_idents_unarized arity ~id + in + let num_fields_prior_to_projected_fields = + Misc.Stdlib.List.split_at n layouts + |> fst + |> List.map Flambda_arity.Component_for_creation.from_lambda + |> Flambda_arity.create |> Flambda_arity.cardinal_unarized + in + if unboxed_product_debug () + then + Format.eprintf "num_fields_prior_to_projected_fields %d\n%!" + num_fields_prior_to_projected_fields; + let num_projected_fields = Flambda_arity.cardinal_unarized field_arity in + let ids_projected_fields = + Array.sub + (Array.of_list ids_all_fields_with_kinds) + num_fields_prior_to_projected_fields num_projected_fields + |> Array.to_list + (* CR mshinwell: try to keep this as an array? *) + in + let env = + if num_projected_fields <> 1 + then + (* If the field being projected is an unboxed product, we must ensure + any occurrences of [id] get expanded to the individual fields, just + like we do in the [Pmake_unboxed_product] case above. *) + Env.register_unboxed_product env ~unboxed_product:id + ~before_unarization:field_arity_component ~fields:ids_projected_fields + else env + in + if unboxed_product_debug () + then + Format.eprintf + "Unboxed projection: emitting binding of %d ids, num projected fields %d\n\ + %!" + (List.length ids_all_fields_with_kinds) + (List.length ids_projected_fields); + let field_mask = + List.mapi + (fun cur_field (field, kind) -> + if cur_field < num_fields_prior_to_projected_fields + || cur_field + >= num_fields_prior_to_projected_fields + num_projected_fields + then None + else + match ids_projected_fields with + | [(_, kind)] -> + (* If no splitting is occurring, we must cause [id] to be bound, + being the original bound variable from the enclosing [Llet]. *) + Some (id, kind) + | [] | _ :: _ -> + (* In all other cases we cause one of the variables representing + the individual fields of the unboxed product to be bound. *) + Some (field, kind)) + ids_all_fields_with_kinds + in + Unboxed_binding (field_mask, env) + | Punboxed_product_field _, (([] | _ :: _) as args) -> + Misc.fatal_errorf + "Punboxed_product_field only takes one argument, but found: %a" + (Format.pp_print_list ~pp_sep:Format.pp_print_space Printlambda.lambda) + args | _, _ -> Primitive (prim, args, loc) [@@ocaml.warning "-fragile-match"] @@ -790,17 +1020,54 @@ let let_cont_nonrecursive_with_extra_params acc env ccenv ~is_exn_handler let { Env.body_env; handler_env; extra_params } = Env.add_continuation env cont ~push_to_try_stack:is_exn_handler Nonrecursive in - let params = - List.map - (fun (id, visible, kind) -> - id, visible, Flambda_kind.With_subkind.from_lambda kind) - params + let orig_params = params in + let handler_env, params_rev = + List.fold_left + (fun (handler_env, params_rev) (id, visible, layout) -> + let arity_component = + Flambda_arity.Component_for_creation.from_lambda layout + in + match arity_component with + | Singleton kind -> + let param = id, visible, kind in + handler_env, param :: params_rev + | Unboxed_product _ -> + let arity = Flambda_arity.create [arity_component] in + let fields = + List.mapi + (fun n kind -> + let field = + Ident.create_local + (Printf.sprintf "%s_unboxed%d" (Ident.unique_name id) n) + in + field, kind) + (Flambda_arity.unarize arity) + in + let handler_env = + Env.register_unboxed_product handler_env ~unboxed_product:id + ~before_unarization:arity_component ~fields + in + let new_params_rev = + List.map (fun (id, kind) -> id, IR.Not_user_visible, kind) fields + |> List.rev + in + handler_env, new_params_rev @ params_rev) + (handler_env, []) params in + let params = List.rev params_rev in + if List.compare_lengths params orig_params <> 0 + then + if unboxed_product_debug () + then + Format.eprintf + "Continuation %a has unboxed arities: orig_params %a, params %a\n%!" + Continuation.print cont + (Format.pp_print_list ~pp_sep:Format.pp_print_space Ident.print) + (List.map (fun (id, _, _) -> id) orig_params) + (Format.pp_print_list ~pp_sep:Format.pp_print_space Ident.print) + (List.map (fun (id, _, _) -> id) params); let extra_params = - List.map - (fun (id, kind) -> - id, IR.User_visible, Flambda_kind.With_subkind.from_lambda kind) - extra_params + List.map (fun (id, kind) -> id, IR.User_visible, kind) extra_params in let handler acc ccenv = handler acc handler_env ccenv in let body acc ccenv = body acc body_env ccenv cont in @@ -872,9 +1139,16 @@ let wrap_return_continuation acc env ccenv (apply : IR.apply) = | [] -> CC.close_apply acc ccenv { apply with continuation; region } | _ :: _ -> let wrapper_cont = Continuation.create () in - let return_value = Ident.create_local "return_val" in + let return_kinds = Flambda_arity.unarize apply.return_arity in + let return_value_components = + List.mapi + (fun i _ -> Ident.create_local (Printf.sprintf "return_val%d" i)) + return_kinds + in let args = - List.map (fun var : IR.simple -> Var var) (return_value :: extra_args) + List.map + (fun var : IR.simple -> Var var) + (return_value_components @ extra_args) in let dbg = Debuginfo.none in let handler acc ccenv = @@ -884,20 +1158,14 @@ let wrap_return_continuation acc env ccenv (apply : IR.apply) = CC.close_apply acc ccenv { apply with continuation = wrapper_cont; region } in - let return_arity = - match Flambda_arity.to_list apply.return_arity with - | [return_kind] -> return_kind - | _ :: _ -> - Misc.fatal_errorf - "Multiple return values for application of %a not supported yet" - Ident.print apply.func - | [] -> - Misc.fatal_errorf "Nullary return arity for application of %a" - Ident.print apply.func + let params = + List.map2 + (fun return_value_component kind -> + return_value_component, IR.Not_user_visible, kind) + return_value_components return_kinds in CC.close_let_cont acc ccenv ~name:wrapper_cont ~is_exn_handler:false - ~params:[return_value, Not_user_visible, return_arity] - ~recursive:Nonrecursive ~body ~handler + ~params ~recursive:Nonrecursive ~body ~handler in restore_continuation_context acc env ccenv apply.continuation ~close_early body @@ -982,32 +1250,32 @@ let primitive_can_raise (prim : Lambda.primitive) = | Pbigstring_set_64 true | Pctconst _ | Pbswap16 | Pbbswap _ | Pint_as_pointer | Popaque _ | Pprobe_is_enabled _ | Pobj_dup | Pobj_magic _ | Pbox_float _ | Punbox_float - | Punbox_int _ | Pbox_int _ -> + | Punbox_int _ | Pbox_int _ | Pmake_unboxed_product _ + | Punboxed_product_field _ -> false -let primitive_result_kind (prim : Lambda.primitive) : - Flambda_kind.With_subkind.t = +let primitive_result_kind (prim : Lambda.primitive) : _ Flambda_arity.t = match prim with | Pccall { prim_native_repr_res = _, Untagged_int; _ } -> - Flambda_kind.With_subkind.tagged_immediate + Flambda_arity.create_singletons [Flambda_kind.With_subkind.tagged_immediate] | Pccall { prim_native_repr_res = _, Unboxed_float; _ } | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ | Paddfloat _ | Psubfloat _ | Pmulfloat _ | Pdivfloat _ | Pfloatfield _ | Parrayrefs Pfloatarray | Parrayrefu Pfloatarray | Pbigarrayref (_, _, (Pbigarray_float32 | Pbigarray_float64), _) -> - Flambda_kind.With_subkind.boxed_float + Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_float] | Pccall { prim_native_repr_res = _, Unboxed_integer Pnativeint; _ } | Pbigarrayref (_, _, Pbigarray_native_int, _) -> - Flambda_kind.With_subkind.boxed_nativeint + Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_nativeint] | Pccall { prim_native_repr_res = _, Unboxed_integer Pint32; _ } | Pstring_load_32 _ | Pbytes_load_32 _ | Pbigstring_load_32 _ | Pbigarrayref (_, _, Pbigarray_int32, _) -> - Flambda_kind.With_subkind.boxed_int32 + Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_int32] | Pccall { prim_native_repr_res = _, Unboxed_integer Pint64; _ } | Pstring_load_64 _ | Pbytes_load_64 _ | Pbigstring_load_64 _ | Pbigarrayref (_, _, Pbigarray_int64, _) -> - Flambda_kind.With_subkind.boxed_int64 + Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_int64] | Pnegint | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pmodint _ | Pdivint _ | Pignore | Psequand | Psequor | Pnot | Pbytesrefs | Pstringrefs | Pbytessets | Pstring_load_16 _ @@ -1028,7 +1296,7 @@ let primitive_result_kind (prim : Lambda.primitive) : ( Pbigarray_sint8 | Pbigarray_uint8 | Pbigarray_sint16 | Pbigarray_uint16 | Pbigarray_caml_int ), _ ) -> - Flambda_kind.With_subkind.tagged_immediate + Flambda_arity.create_singletons [Flambda_kind.With_subkind.tagged_immediate] | Pdivbint { size = bi; _ } | Pmodbint { size = bi; _ } | Pandbint (bi, _) @@ -1044,16 +1312,18 @@ let primitive_result_kind (prim : Lambda.primitive) : | Pbintofint (bi, _) | Pcvtbint (_, bi, _) | Pbbswap (bi, _) - | Pbox_int (bi, _) -> ( - match bi with - | Pint32 -> Flambda_kind.With_subkind.boxed_int32 - | Pint64 -> Flambda_kind.With_subkind.boxed_int64 - | Pnativeint -> Flambda_kind.With_subkind.boxed_nativeint) + | Pbox_int (bi, _) -> + Flambda_arity.create_singletons + [ (match bi with + | Pint32 -> Flambda_kind.With_subkind.boxed_int32 + | Pint64 -> Flambda_kind.With_subkind.boxed_int64 + | Pnativeint -> Flambda_kind.With_subkind.boxed_nativeint) ] | Popaque layout | Pobj_magic layout -> - Flambda_kind.With_subkind.from_lambda layout + Flambda_arity.create_singletons + [Flambda_kind.With_subkind.from_lambda layout] | Praise _ -> (* CR ncourant: this should be bottom, but we don't have it *) - Flambda_kind.With_subkind.any_value + Flambda_arity.create_singletons [Flambda_kind.With_subkind.any_value] | Pccall { prim_native_repr_res = _, Same_as_ocaml_repr; _ } | Parrayrefs (Pgenarray | Paddrarray) | Parrayrefu (Pgenarray | Paddrarray) @@ -1064,36 +1334,75 @@ let primitive_result_kind (prim : Lambda.primitive) : | Pbigarrayref (_, _, (Pbigarray_complex32 | Pbigarray_complex64 | Pbigarray_unknown), _) | Pint_as_pointer | Pobj_dup -> - Flambda_kind.With_subkind.any_value - | Pbox_float _ -> Flambda_kind.With_subkind.boxed_float - | Punbox_float -> Flambda_kind.With_subkind.naked_float - | Punbox_int bi -> ( - match bi with - | Pint32 -> Flambda_kind.With_subkind.naked_int32 - | Pint64 -> Flambda_kind.With_subkind.naked_int64 - | Pnativeint -> Flambda_kind.With_subkind.naked_nativeint) + Flambda_arity.create_singletons [Flambda_kind.With_subkind.any_value] + | Pbox_float _ -> + Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_float] + | Punbox_float -> + Flambda_arity.create_singletons [Flambda_kind.With_subkind.naked_float] + | Punbox_int bi -> + Flambda_arity.create_singletons + [ (match bi with + | Pint32 -> Flambda_kind.With_subkind.naked_int32 + | Pint64 -> Flambda_kind.With_subkind.naked_int64 + | Pnativeint -> Flambda_kind.With_subkind.naked_nativeint) ] + | Pmake_unboxed_product _ | Punboxed_product_field _ -> + Misc.fatal_errorf "Primitive not allowed here:@ %a" Printlambda.primitive + prim + +type non_tail_continuation = + Acc.t -> + Env.t -> + CCenv.t -> + IR.simple list -> + [`Unarized | `Complex] Flambda_arity.Component_for_creation.t -> + Expr_with_acc.t + +type non_tail_list_continuation = + Acc.t -> + Env.t -> + CCenv.t -> + IR.simple list -> + [`Unarized | `Complex] Flambda_arity.Component_for_creation.t list -> + Expr_with_acc.t type cps_continuation = | Tail of Continuation.t - | Non_tail of (Acc.t -> Env.t -> CCenv.t -> IR.simple -> Expr_with_acc.t) + | Non_tail of non_tail_continuation -let apply_cps_cont_simple k ?(dbg = Debuginfo.none) acc env ccenv simple = +let apply_cps_cont_simple k ?(dbg = Debuginfo.none) acc env ccenv simples + (arity_component : + [`Unarized | `Complex] Flambda_arity.Component_for_creation.t) = match k with - | Tail k -> apply_cont_with_extra_args acc env ccenv ~dbg k None [simple] - | Non_tail k -> k acc env ccenv simple + | Tail k -> apply_cont_with_extra_args acc env ccenv ~dbg k None simples + | Non_tail k -> k acc env ccenv simples arity_component -let apply_cps_cont k ?dbg acc env ccenv id = - apply_cps_cont_simple k ?dbg acc env ccenv (IR.Var id) +let apply_cps_cont k ?dbg acc env ccenv id + (arity_component : + [`Unarized | `Complex] Flambda_arity.Component_for_creation.t) = + apply_cps_cont_simple k ?dbg acc env ccenv [IR.Var id] arity_component -let maybe_insert_let_cont result_var_name kind k acc env ccenv body = +let maybe_insert_let_cont result_var_name layout k acc env ccenv body = match k with | Tail k -> body acc env ccenv k | Non_tail k -> - let result_var = Ident.create_local result_var_name in - let_cont_nonrecursive_with_extra_params acc env ccenv ~is_exn_handler:false - ~params:[result_var, IR.Not_user_visible, kind] - ~handler:(fun acc env ccenv -> k acc env ccenv (IR.Var result_var)) - ~body + let arity_component = + Flambda_arity.Component_for_creation.from_lambda layout + in + let arity = Flambda_arity.create [arity_component] in + if Flambda_arity.cardinal_unarized arity < 1 + then + let_cont_nonrecursive_with_extra_params acc env ccenv + ~is_exn_handler:false ~params:[] + ~handler:(fun acc env ccenv -> k acc env ccenv [] arity_component) + ~body + else + let result_var = Ident.create_local result_var_name in + let_cont_nonrecursive_with_extra_params acc env ccenv + ~is_exn_handler:false + ~params:[result_var, IR.Not_user_visible, layout] + ~handler:(fun acc env ccenv -> + k acc env ccenv [IR.Var result_var] arity_component) + ~body let name_if_not_var acc ccenv name simple kind body = match simple with @@ -1106,13 +1415,42 @@ let name_if_not_var acc ccenv name simple kind body = let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) (k_exn : Continuation.t) : Expr_with_acc.t = match lam with - | Lvar id -> + | Lvar id -> ( assert (not (Env.is_mutable env id)); - apply_cps_cont k acc env ccenv id + if unboxed_product_debug () + then + Format.eprintf "checking for unboxed product fields of %a\n%!" Ident.print + id; + match Env.get_unboxed_product_fields env id with + | None -> + if unboxed_product_debug () then Format.eprintf "...no unboxed fields\n%!"; + let kind = + match CCenv.find_simple_to_substitute_exn ccenv id with + | exception Not_found -> snd (CCenv.find_var ccenv id) + | _, kind -> kind + in + let arity_component = + Flambda_arity.Component_for_creation.Singleton kind + in + apply_cps_cont k acc env ccenv id arity_component + | Some (before_unarization, fields) -> + if unboxed_product_debug () + then + Format.eprintf "...got unboxed fields: (%a)\n%!" + (Format.pp_print_list ~pp_sep:Format.pp_print_space Ident.print) + fields; + let fields = List.map (fun id -> IR.Var id) fields in + apply_cps_cont_simple k acc env ccenv fields before_unarization) | Lmutvar id -> - let return_id = Env.get_mutable_variable env id in + (* CR mshinwell: note: mutable variables of non-singleton layouts are not + supported *) + let return_id, kind = Env.get_mutable_variable_with_kind env id in apply_cps_cont k acc env ccenv return_id - | Lconst const -> apply_cps_cont_simple k acc env ccenv (IR.Const const) + (Flambda_arity.Component_for_creation.Singleton kind) + | Lconst const -> + apply_cps_cont_simple k acc env ccenv [IR.Const const] + (* CR mshinwell: improve layout here *) + (Singleton Flambda_kind.With_subkind.any_value) | Lapply { ap_func; ap_args; @@ -1137,7 +1475,10 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) let func = cps_function env ~fid:id ~recursive:(Non_recursive : Recursive.t) func in - let body acc ccenv = apply_cps_cont k ~dbg acc env ccenv id in + let body acc ccenv = + apply_cps_cont k ~dbg acc env ccenv id + (Singleton Flambda_kind.With_subkind.any_value) + in CC.close_let_rec acc ccenv ~function_declarations:[func] ~body ~current_region:(Env.current_region env) | Lmutlet (value_kind, id, defining_expr, body) -> @@ -1147,7 +1488,8 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) ~body:(fun acc env ccenv after_defining_expr -> cps_tail acc env ccenv defining_expr after_defining_expr k_exn) ~handler:(fun acc env ccenv -> - let env, new_id = Env.register_mutable_variable env id value_kind in + let kind = Flambda_kind.With_subkind.from_lambda value_kind in + let env, new_id = Env.register_mutable_variable env id kind in let body acc ccenv = cps acc env ccenv body k k_exn in CC.close_let acc ccenv new_id User_visible (Flambda_kind.With_subkind.from_lambda value_kind) @@ -1176,7 +1518,9 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) id, Lprim (prim, args, loc), body ) -> ( - match transform_primitive env prim args loc with + if unboxed_product_debug () + then Format.eprintf "Handling let-binding: %a\n%!" Printlambda.lambda lam; + match transform_primitive env id prim args loc with | Primitive (prim, args, loc) -> (* This case avoids extraneous continuations. *) let exn_continuation : IR.exn_continuation option = @@ -1189,7 +1533,7 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) else None in cps_non_tail_list acc env ccenv args - (fun acc env ccenv args -> + (fun acc env ccenv args _arity -> let body acc ccenv = cps acc env ccenv body k k_exn in let region = Env.current_region env in CC.close_let acc ccenv id User_visible @@ -1197,6 +1541,45 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) (Prim { prim; args; loc; exn_continuation; region }) ~body) k_exn + | Unboxed_binding (ids_with_kinds, env) -> + cps_non_tail_list acc env ccenv args + (fun acc env ccenv (args : IR.simple list) _arity -> + if unboxed_product_debug () + then + Format.eprintf "Unboxed_binding: ids_with_kinds=(%a) args=(%a)\n%!" + (Format.pp_print_list ~pp_sep:Format.pp_print_space + (Misc.Stdlib.Option.print (fun ppf (id, kind) -> + Format.fprintf ppf "%a :: %a" Ident.print id + Flambda_kind.With_subkind.print kind))) + ids_with_kinds + (Format.pp_print_list ~pp_sep:Format.pp_print_space + IR.print_simple) + args; + let body acc ccenv = cps acc env ccenv body k k_exn in + if List.compare_lengths ids_with_kinds args <> 0 + then + Misc.fatal_errorf + "ids_with_kinds (%a) doesn't match args (%a) for:@ %a" + (Format.pp_print_list ~pp_sep:Format.pp_print_space + (Misc.Stdlib.Option.print (fun ppf (id, kind) -> + Format.fprintf ppf "%a :: %a" Ident.print id + Flambda_kind.With_subkind.print kind))) + ids_with_kinds + (Format.pp_print_list ~pp_sep:Format.pp_print_space + IR.print_simple) + args Printlambda.lambda lam; + let builder = + List.fold_left2 + (fun body id_and_kind_opt arg acc ccenv -> + match id_and_kind_opt with + | None -> body acc ccenv + | Some (id, kind) -> + CC.close_let acc ccenv id Not_user_visible kind (Simple arg) + ~body) + body ids_with_kinds args + in + builder acc ccenv) + k_exn | Transformed lam -> cps acc env ccenv (L.Llet (let_kind, layout, id, lam, body)) k k_exn) | Llet @@ -1212,7 +1595,8 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) Misc.fatal_errorf "Lassign on non-mutable variable %a" Ident.print being_assigned; cps_non_tail_simple acc env ccenv new_value - (fun acc env ccenv new_value -> + (fun acc env ccenv new_value _arity -> + let new_value = must_be_singleton_simple new_value in let env, new_id = Env.update_mutable_variable env being_assigned in let body acc ccenv = let body acc ccenv = cps acc env ccenv body k k_exn in @@ -1223,9 +1607,8 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) let value_kind = snd (Env.get_mutable_variable_with_kind env being_assigned) in - CC.close_let acc ccenv new_id User_visible - (Flambda_kind.With_subkind.from_lambda value_kind) - (Simple new_value) ~body) + CC.close_let acc ccenv new_id User_visible value_kind (Simple new_value) + ~body) k_exn | Llet ((Strict | Alias | StrictOpt), layout, id, defining_expr, body) -> let_cont_nonrecursive_with_extra_params acc env ccenv ~is_exn_handler:false @@ -1256,30 +1639,116 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) ~current_region:(Env.current_region env) | Dissected lam -> cps acc env ccenv lam k k_exn) | Lprim (prim, args, loc) -> ( - match transform_primitive env prim args loc with - | Primitive (prim, args, loc) -> - let name = Printlambda.name_of_primitive prim in - let result_var = Ident.create_local name in - let exn_continuation : IR.exn_continuation option = - if primitive_can_raise prim - then - Some - { exn_handler = k_exn; - extra_args = extra_args_for_exn_continuation env k_exn - } - else None + match prim with + | Pmake_unboxed_product _ | Punboxed_product_field _ -> + (* This transformation cannot be done for [Praise] (because of the bottom + layout in Lambda) and is probably less efficient than the normal code + path in the next clause. So for the moment we just do it for the + unboxed product cases, as it simplifies matters. *) + (* CR mshinwell: One note though is that [primitive_result_kind] could be + deleted if we could use a path like this all the time. *) + let id = Ident.create_local "prim" in + let result_layout = + match prim with + | Pmake_unboxed_product layouts -> L.Punboxed_product layouts + | Punboxed_product_field (field, layouts) -> + (Array.of_list layouts).(field) + | Pbytes_to_string | Pbytes_of_string | Pignore | Pgetglobal _ + | Psetglobal _ | Pgetpredef _ | Pmakeblock _ | Pmakefloatblock _ + | Pfield _ | Pfield_computed _ | Psetfield _ | Psetfield_computed _ + | Pfloatfield _ | Psetfloatfield _ | Pduprecord _ | Pccall _ | Praise _ + | Psequand | Psequor | Pnot | Pnegint | Paddint | Psubint | Pmulint + | Pdivint _ | Pmodint _ | Pandint | Porint | Pxorint | Plslint | Plsrint + | Pasrint | Pintcomp _ | Pcompare_ints | Pcompare_floats + | Pcompare_bints _ | Poffsetint _ | Poffsetref _ | Pintoffloat + | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ | Paddfloat _ | Psubfloat _ + | Pmulfloat _ | Pdivfloat _ | Pfloatcomp _ | Pstringlength | Pstringrefu + | Pstringrefs | Pbyteslength | Pbytesrefu | Pbytessetu | Pbytesrefs + | Pbytessets | Pmakearray _ | Pduparray _ | Parraylength _ + | Parrayrefu _ | Parraysetu _ | Parrayrefs _ | Parraysets _ | Pisint _ + | Pisout | Pbintofint _ | Pintofbint _ | Pcvtbint _ | Pnegbint _ + | Paddbint _ | Psubbint _ | Pmulbint _ | Pdivbint _ | Pmodbint _ + | Pandbint _ | Porbint _ | Pxorbint _ | Plslbint _ | Plsrbint _ + | Pasrbint _ | Pbintcomp _ | Pbigarrayref _ | Pbigarrayset _ + | Pbigarraydim _ | Pstring_load_16 _ | Pstring_load_32 _ + | Pstring_load_64 _ | Pbytes_load_16 _ | Pbytes_load_32 _ + | Pbytes_load_64 _ | Pbytes_set_16 _ | Pbytes_set_32 _ | Pbytes_set_64 _ + | Pbigstring_load_16 _ | Pbigstring_load_32 _ | Pbigstring_load_64 _ + | Pbigstring_set_16 _ | Pbigstring_set_32 _ | Pbigstring_set_64 _ + | Pctconst _ | Pbswap16 | Pbbswap _ | Pint_as_pointer | Popaque _ + | Pprobe_is_enabled _ | Pobj_dup | Pobj_magic _ | Punbox_float + | Pbox_float _ | Punbox_int _ | Pbox_int _ | Parray_of_iarray + | Parray_to_iarray -> + assert false in - let current_region = Env.current_region env in - let dbg = Debuginfo.from_location loc in - cps_non_tail_list acc env ccenv args - (fun acc env ccenv args -> - let body acc ccenv = apply_cps_cont ~dbg k acc env ccenv result_var in - CC.close_let acc ccenv result_var Not_user_visible - (primitive_result_kind prim) - (Prim { prim; args; loc; exn_continuation; region = current_region }) - ~body) - k_exn - | Transformed lam -> cps acc env ccenv lam k k_exn) + cps acc env ccenv + (L.Llet (Strict, result_layout, id, lam, L.Lvar id)) + k k_exn + | Pbytes_to_string | Pbytes_of_string | Pignore | Pgetglobal _ + | Psetglobal _ | Pgetpredef _ | Pmakeblock _ | Pmakefloatblock _ | Pfield _ + | Pfield_computed _ | Psetfield _ | Psetfield_computed _ | Pfloatfield _ + | Psetfloatfield _ | Pduprecord _ | Pccall _ | Praise _ | Psequand | Psequor + | Pnot | Pnegint | Paddint | Psubint | Pmulint | Pdivint _ | Pmodint _ + | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ + | Pcompare_ints | Pcompare_floats | Pcompare_bints _ | Poffsetint _ + | Poffsetref _ | Pintoffloat | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ + | Paddfloat _ | Psubfloat _ | Pmulfloat _ | Pdivfloat _ | Pfloatcomp _ + | Pstringlength | Pstringrefu | Pstringrefs | Pbyteslength | Pbytesrefu + | Pbytessetu | Pbytesrefs | Pbytessets | Pmakearray _ | Pduparray _ + | Parraylength _ | Parrayrefu _ | Parraysetu _ | Parrayrefs _ | Parraysets _ + | Pisint _ | Pisout | Pbintofint _ | Pintofbint _ | Pcvtbint _ | Pnegbint _ + | Paddbint _ | Psubbint _ | Pmulbint _ | Pdivbint _ | Pmodbint _ + | Pandbint _ | Porbint _ | Pxorbint _ | Plslbint _ | Plsrbint _ | Pasrbint _ + | Pbintcomp _ | Pbigarrayref _ | Pbigarrayset _ | Pbigarraydim _ + | Pstring_load_16 _ | Pstring_load_32 _ | Pstring_load_64 _ + | Pbytes_load_16 _ | Pbytes_load_32 _ | Pbytes_load_64 _ | Pbytes_set_16 _ + | Pbytes_set_32 _ | Pbytes_set_64 _ | Pbigstring_load_16 _ + | Pbigstring_load_32 _ | Pbigstring_load_64 _ | Pbigstring_set_16 _ + | Pbigstring_set_32 _ | Pbigstring_set_64 _ | Pctconst _ | Pbswap16 + | Pbbswap _ | Pint_as_pointer | Popaque _ | Pprobe_is_enabled _ | Pobj_dup + | Pobj_magic _ | Punbox_float | Pbox_float _ | Punbox_int _ | Pbox_int _ + | Parray_of_iarray | Parray_to_iarray -> ( + match + transform_primitive env (Ident.create_local "dummy") prim args loc + with + | Primitive (prim, args, loc) -> ( + let name = Printlambda.name_of_primitive prim in + let result_var = Ident.create_local name in + let exn_continuation : IR.exn_continuation option = + if primitive_can_raise prim + then + Some + { exn_handler = k_exn; + extra_args = extra_args_for_exn_continuation env k_exn + } + else None + in + let current_region = Env.current_region env in + let dbg = Debuginfo.from_location loc in + let arity = primitive_result_kind prim in + match Flambda_arity.must_be_one_param arity with + | None -> + Misc.fatal_errorf + "Expected the following Lprim to require exactly one\n\ + \ variable binding:@ %a" Printlambda.lambda lam + | Some kind -> + cps_non_tail_list acc env ccenv args + (fun acc env ccenv args _arity -> + let body acc ccenv = + apply_cps_cont ~dbg k acc env ccenv result_var (Singleton kind) + in + CC.close_let acc ccenv result_var Not_user_visible kind + (Prim + { prim; + args; + loc; + exn_continuation; + region = current_region + }) + ~body) + k_exn) + | Unboxed_binding _ -> assert false + | Transformed lam -> cps acc env ccenv lam k k_exn)) | Lswitch (scrutinee, switch, loc, kind) -> maybe_insert_let_cont "switch_result" kind k acc env ccenv (fun acc env ccenv k -> @@ -1293,7 +1762,7 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) | Lstaticraise (static_exn, args) -> let continuation = Env.get_static_exn_continuation env static_exn in cps_non_tail_list acc env ccenv args - (fun acc env ccenv args -> + (fun acc env ccenv args _arity -> let extra_args = List.map (fun var : IR.simple -> Var var) @@ -1314,10 +1783,18 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) else Nonrecursive in let params = - List.map - (fun (arg, kind) -> - arg, IR.User_visible, Flambda_kind.With_subkind.from_lambda kind) - (args @ extra_params) + let args = + List.map + (fun (arg, kind) -> + arg, IR.User_visible, Flambda_kind.With_subkind.from_lambda kind) + args + in + let extra_params = + List.map + (fun (extra_param, kind) -> extra_param, IR.User_visible, kind) + extra_params + in + args @ extra_params in let handler acc ccenv = let ccenv = CCenv.set_not_at_toplevel ccenv in @@ -1328,12 +1805,13 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) ~params ~recursive ~body ~handler) | Lsend (meth_kind, meth, obj, args, pos, mode, loc, layout) -> cps_non_tail_simple acc env ccenv obj - (fun acc env ccenv obj -> + (fun acc env ccenv obj _obj_arity -> + let obj = must_be_singleton_simple obj in cps_non_tail_var "meth" acc env ccenv meth Flambda_kind.With_subkind.any_value - (fun acc env ccenv meth -> + (fun acc env ccenv meth _meth_arity -> cps_non_tail_list acc env ccenv args - (fun acc env ccenv args -> + (fun acc env ccenv args args_arity -> maybe_insert_let_cont "send_result" layout k acc env ccenv (fun acc env ccenv k -> let exn_continuation : IR.exn_continuation = @@ -1353,8 +1831,9 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) probe = None; mode; region = Env.current_region env; + args_arity = Flambda_arity.create args_arity; return_arity = - Flambda_arity.create + Flambda_arity.create_singletons [Flambda_kind.With_subkind.from_lambda layout] } in @@ -1424,7 +1903,7 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) let lam = switch_for_if_then_else ~cond ~ifso ~ifnot ~kind in cps acc env ccenv lam k k_exn | Lsequence (lam1, lam2) -> - let k acc env ccenv _value = cps acc env ccenv lam2 k k_exn in + let k acc env ccenv _value _arity = cps acc env ccenv lam2 k k_exn in cps_non_tail_simple acc env ccenv lam1 k k_exn | Lwhile { wh_cond = cond; wh_body = body } -> (* CR-someday mshinwell: make use of wh_cond_region / wh_body_region? *) @@ -1445,17 +1924,18 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) Misc.fatal_errorf "Lassign on non-mutable variable %a" Ident.print being_assigned; cps_non_tail_simple acc env ccenv new_value - (fun acc env ccenv new_value -> + (fun acc env ccenv new_value _arity -> + let new_value = must_be_singleton_simple new_value in let env, new_id = Env.update_mutable_variable env being_assigned in let body acc ccenv = - apply_cps_cont_simple k acc env ccenv (Const L.const_unit) + apply_cps_cont_simple k acc env ccenv [Const L.const_unit] + (Singleton Flambda_kind.With_subkind.tagged_immediate) in let _, value_kind = Env.get_mutable_variable_with_kind env being_assigned in - CC.close_let acc ccenv new_id User_visible - (Flambda_kind.With_subkind.from_lambda value_kind) - (Simple new_value) ~body) + CC.close_let acc ccenv new_id User_visible value_kind (Simple new_value) + ~body) k_exn | Levent (body, _event) -> cps acc env ccenv body k k_exn | Lifused _ -> @@ -1527,24 +2007,48 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) apply_cont_with_extra_args acc env ccenv ~dbg k None [IR.Var wrap_return])))) -and cps_non_tail_simple acc env ccenv lam k k_exn = +and cps_non_tail_simple : + Acc.t -> + Env.t -> + CCenv.t -> + Lambda.lambda -> + non_tail_continuation -> + Continuation.t -> + Expr_with_acc.t = + fun acc env ccenv lam (k : non_tail_continuation) k_exn -> cps acc env ccenv lam (Non_tail k) k_exn -and cps_non_tail_var name acc env ccenv lam kind k k_exn = +and cps_non_tail_var : + string -> + Acc.t -> + Env.t -> + CCenv.t -> + Lambda.lambda -> + Flambda_kind.With_subkind.t -> + (Acc.t -> + Env.t -> + CCenv.t -> + Ident.t -> + [`Unarized | `Complex] Flambda_arity.Component_for_creation.t -> + Expr_with_acc.t) -> + Continuation.t -> + Expr_with_acc.t = + fun name acc env ccenv lam kind k k_exn -> cps_non_tail_simple acc env ccenv lam - (fun acc env ccenv simple -> + (fun acc env ccenv simple arity -> + let simple = must_be_singleton_simple simple in name_if_not_var acc ccenv name simple kind (fun var acc ccenv -> - k acc env ccenv var)) + k acc env ccenv var arity)) k_exn and cps_tail_apply acc env ccenv ap_func ap_args ap_region_close ap_mode ap_loc ap_inlined ap_probe ap_return (k : Continuation.t) (k_exn : Continuation.t) : Expr_with_acc.t = cps_non_tail_list acc env ccenv ap_args - (fun acc env ccenv args -> + (fun acc env ccenv args args_arity -> cps_non_tail_var "func" acc env ccenv ap_func Flambda_kind.With_subkind.any_value - (fun acc env ccenv func -> + (fun acc env ccenv func _func_arity -> let exn_continuation : IR.exn_continuation = { exn_handler = k_exn; extra_args = extra_args_for_exn_continuation env k_exn @@ -1562,9 +2066,10 @@ and cps_tail_apply acc env ccenv ap_func ap_args ap_region_close ap_mode ap_loc probe = ap_probe; mode = ap_mode; region = Env.current_region env; + args_arity = Flambda_arity.create args_arity; return_arity = Flambda_arity.create - [Flambda_kind.With_subkind.from_lambda ap_return] + [Flambda_arity.Component_for_creation.from_lambda ap_return] } in wrap_return_continuation acc env ccenv apply) @@ -1575,23 +2080,34 @@ and cps_tail acc env ccenv (lam : L.lambda) (k : Continuation.t) (k_exn : Continuation.t) : Expr_with_acc.t = cps acc env ccenv lam (Tail k) k_exn -and cps_non_tail_list acc env ccenv lams k k_exn = +and cps_non_tail_list : + Acc.t -> + Env.t -> + CCenv.t -> + Lambda.lambda list -> + non_tail_list_continuation -> + Continuation.t -> + Expr_with_acc.t = + fun acc env ccenv lams (k : non_tail_list_continuation) k_exn -> let lams = List.rev lams in (* Always evaluate right-to-left. *) cps_non_tail_list_core acc env ccenv lams - (fun acc env ccenv ids -> k acc env ccenv (List.rev ids)) + (fun acc env ccenv ids + (arity : + [`Unarized | `Complex] Flambda_arity.Component_for_creation.t list) -> + k acc env ccenv (List.rev ids) (List.rev arity)) k_exn and cps_non_tail_list_core acc env ccenv (lams : L.lambda list) - (k : Acc.t -> Env.t -> CCenv.t -> IR.simple list -> Expr_with_acc.t) - (k_exn : Continuation.t) = + (k : non_tail_list_continuation) (k_exn : Continuation.t) = match lams with - | [] -> k acc env ccenv [] + | [] -> k acc env ccenv [] [] | lam :: lams -> cps_non_tail_simple acc env ccenv lam - (fun acc env ccenv simple -> + (fun acc env ccenv simples arity -> cps_non_tail_list_core acc env ccenv lams - (fun acc env ccenv simples -> k acc env ccenv (simple :: simples)) + (fun acc env ccenv simples' arity' -> + k acc env ccenv (List.rev simples @ simples') (arity :: arity')) k_exn) k_exn @@ -1690,23 +2206,79 @@ and cps_function env ~fid ~(recursive : Recursive.t) ?precomputed_free_idents (Compilation_unit.get_current_exn ()) ~name:(Ident.name fid) Flambda_kind.With_subkind.any_value in + let params_arity = Flambda_arity.from_lambda_list (List.map snd params) in + let unarized_per_param = Flambda_arity.unarize_per_parameter params_arity in + assert (List.compare_lengths params unarized_per_param = 0); + let unboxed_products = ref Ident.Map.empty in + let params = + List.concat_map + (fun ((param, layout), kinds) -> + match kinds with + | [] -> [] + | [kind] -> [param, kind] + | _ :: _ -> + if unboxed_product_debug () + then + Format.eprintf + "splitting unboxed product for function parameter %a\n%!" + Ident.print param; + let fields = + List.mapi + (fun n kind -> + let ident = + Ident.create_local + (Printf.sprintf "%s_unboxed%d" (Ident.unique_name param) n) + in + ident, kind) + kinds + in + let before_unarization = + Flambda_arity.Component_for_creation.from_lambda layout + in + unboxed_products + := Ident.Map.add param + (before_unarization, fields) + !unboxed_products; + fields) + (List.combine params unarized_per_param) + in + if unboxed_product_debug () + then + if List.compare_lengths params unarized_per_param <> 0 + then + Format.eprintf "flattened param list for %a:@ %a\n%!" Ident.print fid + (Format.pp_print_list (fun ppf (id, kind) -> + Format.fprintf ppf "%a :: %a" Ident.print id + Flambda_kind.With_subkind.print kind)) + params; + let unboxed_products = !unboxed_products in + let removed_params = Ident.Map.keys unboxed_products in + let return = + Flambda_arity.create + [Flambda_arity.Component_for_creation.from_lambda return] + in let body acc ccenv = let ccenv = CCenv.set_path_to_root ccenv loc in let ccenv = CCenv.set_not_at_toplevel ccenv in + let new_env = + Ident.Map.fold + (fun unboxed_product (before_unarization, fields) new_env -> + if unboxed_product_debug () + then + Format.eprintf + "registering unboxed product for function parameter %a\n%!" + Ident.print unboxed_product; + Env.register_unboxed_product new_env ~unboxed_product + ~before_unarization ~fields) + unboxed_products new_env + in cps_tail acc new_env ccenv body body_cont body_exn_cont in - let params = - List.map - (fun (param, kind) -> param, Flambda_kind.With_subkind.from_lambda kind) - params - in - let return = - Flambda_arity.create [Flambda_kind.With_subkind.from_lambda return] - in Function_decl.create ~let_rec_ident:(Some fid) ~function_slot ~kind ~params - ~return ~return_continuation:body_cont ~exn_continuation ~my_region ~body - ~attr ~loc ~free_idents_of_body recursive ~closure_alloc_mode:mode - ~num_trailing_local_params ~contains_no_escaping_local_allocs:region + ~params_arity ~removed_params ~return ~return_continuation:body_cont + ~exn_continuation ~my_region ~body ~attr ~loc ~free_idents_of_body recursive + ~closure_alloc_mode:mode ~num_trailing_local_params + ~contains_no_escaping_local_allocs:region and cps_switch acc env ccenv (switch : L.lambda_switch) ~condition_dbg ~scrutinee (k : Continuation.t) (k_exn : Continuation.t) : Expr_with_acc.t = @@ -1779,7 +2351,7 @@ and cps_switch acc env ccenv (switch : L.lambda_switch) ~condition_dbg in cps_non_tail_var "scrutinee" acc env ccenv scrutinee Flambda_kind.With_subkind.any_value - (fun acc env ccenv scrutinee -> + (fun acc env ccenv scrutinee _arity -> let ccenv = CCenv.set_not_at_toplevel ccenv in let consts_rev, wrappers = convert_arms_rev env switch.sw_consts [] in let blocks_rev, wrappers = diff --git a/middle_end/flambda2/from_lambda/lambda_to_flambda_primitives.ml b/middle_end/flambda2/from_lambda/lambda_to_flambda_primitives.ml index 46fc5bf934c..df57814b933 100644 --- a/middle_end/flambda2/from_lambda/lambda_to_flambda_primitives.ml +++ b/middle_end/flambda2/from_lambda/lambda_to_flambda_primitives.ml @@ -1213,7 +1213,8 @@ let convert_lprim ~big_endian (prim : L.primitive) (args : Simple.t list) %a (%a)" Printlambda.primitive prim H.print_list_of_simple_or_prim args | ( ( Pignore | Psequand | Psequor | Pbytes_of_string | Pbytes_to_string - | Parray_of_iarray | Parray_to_iarray ), + | Parray_of_iarray | Parray_to_iarray | Pmake_unboxed_product _ + | Punboxed_product_field _ ), _ ) -> Misc.fatal_errorf "[%a] should have been removed by [Lambda_to_flambda.transform_primitive]" diff --git a/middle_end/flambda2/kinds/flambda_arity.ml b/middle_end/flambda2/kinds/flambda_arity.ml index 5ff02e47cd4..0b2c8c8a3d8 100644 --- a/middle_end/flambda2/kinds/flambda_arity.ml +++ b/middle_end/flambda2/kinds/flambda_arity.ml @@ -15,48 +15,134 @@ (**************************************************************************) module Component = struct - type t = Singleton of Flambda_kind.With_subkind.t + type _ t = + | Singleton : Flambda_kind.With_subkind.t -> [> `Unarized] t + | Unboxed_product : _ t list -> [> `Complex] t - let equal_ignoring_subkinds t1 t2 = + let rec equal_ignoring_subkinds : type uc1 uc2. uc1 t -> uc2 t -> bool = + fun t1 t2 -> match t1, t2 with | Singleton kind1, Singleton kind2 -> - Flambda_kind.With_subkind.equal_ignoring_subkind kind1 kind2 + Flambda_kind.With_subkind.equal + (Flambda_kind.With_subkind.erase_subkind kind1) + (Flambda_kind.With_subkind.erase_subkind kind2) + | Unboxed_product ts1, Unboxed_product ts2 -> + Misc.Stdlib.List.equal equal_ignoring_subkinds ts1 ts2 + | Singleton _, Unboxed_product _ | Unboxed_product _, Singleton _ -> false - let equal_exact t1 t2 = + let rec equal_exact : type uc1 uc2. uc1 t -> uc2 t -> bool = + fun t1 t2 -> match t1, t2 with | Singleton kind1, Singleton kind2 -> Flambda_kind.With_subkind.equal kind1 kind2 + | Unboxed_product ts1, Unboxed_product ts2 -> + Misc.Stdlib.List.equal equal_exact ts1 ts2 + | Singleton _, Unboxed_product _ | Unboxed_product _, Singleton _ -> false - let print ~product_above:_ ppf t = - match t with Singleton kind -> Flambda_kind.With_subkind.print ppf kind + let rec print : type uc. Format.formatter -> uc t -> unit = + fun ppf t -> + match t with + | Singleton kind -> Flambda_kind.With_subkind.print ppf kind + | Unboxed_product [] -> Format.pp_print_string ppf "void" + | Unboxed_product ts -> + Format.fprintf ppf "@[%t#%t(%a)@]" Flambda_colours.unboxed_product + Flambda_colours.pop + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf " @<1>\u{2a2f} ") + print) + ts + + let rec unarize : type uc. uc t -> Flambda_kind.With_subkind.t list = + fun t -> + match t with + | Singleton kind -> [kind] + | Unboxed_product [] -> [] + | Unboxed_product ts -> List.concat_map unarize ts end -type t = Component.t list +type 'uc t = 'uc Component.t list + +module Component_for_creation = struct + type 'uc t = 'uc Component.t = + | Singleton : Flambda_kind.With_subkind.t -> [> `Unarized] t + | Unboxed_product : _ t list -> [> `Complex] t + + let rec from_lambda (layout : Lambda.layout) = + match layout with + | Pvalue _ | Punboxed_float | Punboxed_int _ -> + Singleton (Flambda_kind.With_subkind.from_lambda layout) + | Punboxed_product layouts -> Unboxed_product (List.map from_lambda layouts) + | Ptop -> + Misc.fatal_error + "Cannot convert Ptop to Flambda_arity.Component_for_creation" + | Pbottom -> + Misc.fatal_error + "Cannot convert Pbottom to Flambda_arity.Component_for_creation" +end let nullary = [] -let create t = List.map (fun kind -> Component.Singleton kind) t +let create t = t -let to_list t = List.map (fun (Component.Singleton kind) -> kind) t +let create_singletons t = List.map (fun kind -> Component.Singleton kind) t let print ppf t = Format.fprintf ppf "@[%a@]" - (Format.pp_print_list (Component.print ~product_above:true) - ~pp_sep:(fun ppf () -> Format.fprintf ppf " @<1>\u{2a2f} ")) + (Format.pp_print_list Component.print ~pp_sep:(fun ppf () -> + Format.fprintf ppf " @<1>\u{2a2f} ")) t -let equal_ignoring_subkinds t1 t2 = - List.equal Component.equal_ignoring_subkinds t1 t2 +let equal_ignoring_subkinds : type uc1 uc2. uc1 t -> uc2 t -> bool = + fun t1 t2 -> Misc.Stdlib.List.equal Component.equal_ignoring_subkinds t1 t2 -let equal_exact t1 t2 = List.equal Component.equal_exact t1 t2 +let equal_exact : type uc1 uc2. uc1 t -> uc2 t -> bool = + fun t1 t2 -> Misc.Stdlib.List.equal Component.equal_exact t1 t2 -let is_singleton_value t = +let is_one_param_of_kind_value : type uc. uc t -> bool = + fun t -> match t with | [Component.Singleton kind] when Flambda_kind.equal (Flambda_kind.With_subkind.kind kind) Flambda_kind.value -> true - | [] | Component.Singleton _ :: _ -> false + | [] | Component.Singleton _ :: _ | Component.Unboxed_product _ :: _ -> false + +let unarize t = t |> List.map Component.unarize |> List.concat + +let unarize_per_parameter t = t |> List.map Component.unarize + +let unarize_t t = t |> unarize |> create_singletons + +let fresh_idents_unarized t ~id = + List.mapi + (fun n kind -> + let ident = + Ident.create_local + (Printf.sprintf "%s_unboxed%d" (Ident.unique_name id) n) + in + ident, kind) + (unarize t) + +let cardinal_unarized t = List.length (unarize t) + +let num_params t = List.length t + +let rec must_be_one_param : type uc. uc t -> Flambda_kind.With_subkind.t option + = + fun t -> + match t with + | [Component.Singleton kind] -> Some kind + | [Component.Unboxed_product component] -> must_be_one_param component + | [] | (Component.Singleton _ | Component.Unboxed_product _) :: _ -> None + +let from_lambda_list layouts = + layouts |> List.map Component_for_creation.from_lambda |> create -let cardinal t = List.length t +let partially_apply t ~num_non_unarized_params_provided = + if num_non_unarized_params_provided < 0 + || num_non_unarized_params_provided >= List.length t + then + Misc.fatal_errorf "Bad num_non_unarized_params_provided (%d): %a" + num_non_unarized_params_provided print t + else snd (Misc.Stdlib.List.split_at num_non_unarized_params_provided t) diff --git a/middle_end/flambda2/kinds/flambda_arity.mli b/middle_end/flambda2/kinds/flambda_arity.mli index a055dc49283..18d1ec381df 100644 --- a/middle_end/flambda2/kinds/flambda_arity.mli +++ b/middle_end/flambda2/kinds/flambda_arity.mli @@ -14,25 +14,80 @@ (* *) (**************************************************************************) -(** Arities are lists of kinds (with subkinds) used to describe things - such as the kinding of function and continuation parameter lists. *) +(** Arities are used to describe the layouts of things like function and + continuation parameter lists. -type t + In Flambda 2, variables are always assigned kinds, which are at most + register width (presently machine word width, but in the future of SIMD + widths too). Variables from Lambda which cannot be accommodated in one + register, for example if they are of an unboxed product layout, are split + by a process called unarization. -val nullary : t + Despite this, [`Complex] arities preserve the information about any unboxed + products, for later use (e.g. during Cmm translation to optimize + caml_apply). +*) -val create : Flambda_kind.With_subkind.t list -> t +type _ t -val to_list : t -> Flambda_kind.With_subkind.t list +module Component_for_creation : sig + type _ t = + | Singleton : Flambda_kind.With_subkind.t -> [> `Unarized] t + (* The nullary unboxed product is called "void". It is important to + propagate information about void layouts, even though the corresponding + variables have no runtime representation, as they interact with + currying. *) + | Unboxed_product : _ t list -> [> `Complex] t -val cardinal : t -> int + val from_lambda : Lambda.layout -> [`Unarized | `Complex] t +end -val is_singleton_value : t -> bool +(** One component per function or continuation parameter, for example. Each + component may in turn have an arity describing an unboxed product. *) +val create : 'uc Component_for_creation.t list -> 'uc t -val print : Format.formatter -> t -> unit +val create_singletons : Flambda_kind.With_subkind.t list -> [> `Unarized] t -val equal_ignoring_subkinds : t -> t -> bool +(** "No parameters". (Not e.g. "one parameter of type void".) *) +val nullary : [> `Unarized] t + +val num_params : _ t -> int + +val print : Format.formatter -> _ t -> unit + +val equal_ignoring_subkinds : _ t -> _ t -> bool (* It's usually a mistake to use this function, but it's needed for [Compare]. *) -val equal_exact : t -> t -> bool +val equal_exact : _ t -> _ t -> bool + +val is_one_param_of_kind_value : _ t -> bool + +val must_be_one_param : _ t -> Flambda_kind.With_subkind.t option + +(** Converts, in a left-to-right depth-first order, an arity into a flattened + list of kinds for all parameters. *) +val unarize : _ t -> Flambda_kind.With_subkind.t list + +(** Like [unarize] but returns one list per parameter. *) +val unarize_per_parameter : _ t -> Flambda_kind.With_subkind.t list list + +(** Like [unarize] but returns a value of type [t]. *) +val unarize_t : _ t -> [> `Unarized] t + +(** Given an arity and an identifier, produce a list of identifiers (with + corresponding kinds) whose length matches [unarize t], with names derived + from the given identifier. *) +val fresh_idents_unarized : + _ t -> id:Ident.t -> (Ident.t * Flambda_kind.With_subkind.t) list + +(** The length of the list returned by [unarize]. *) +val cardinal_unarized : _ t -> int + +(** Take a list of Lambda layouts, one per parameter, and form the + corresponding arity. *) +val from_lambda_list : Lambda.layout list -> [`Unarized | `Complex] t + +(** Remove the first portion of an arity to correspond to a partial + application. *) +val partially_apply : 'uc t -> num_non_unarized_params_provided:int -> 'uc t diff --git a/middle_end/flambda2/kinds/flambda_kind.ml b/middle_end/flambda2/kinds/flambda_kind.ml index a014ec6e7f8..23dbc96da3a 100644 --- a/middle_end/flambda2/kinds/flambda_kind.ml +++ b/middle_end/flambda2/kinds/flambda_kind.ml @@ -544,6 +544,8 @@ module With_subkind = struct | Punboxed_int Pint32 -> naked_int32 | Punboxed_int Pint64 -> naked_int64 | Punboxed_int Pnativeint -> naked_nativeint + | Punboxed_product _ -> + Misc.fatal_error "Punboxed_product disallowed here, use Flambda_arity" include Container_types.Make (struct type nonrec t = t diff --git a/middle_end/flambda2/parser/fexpr_to_flambda.ml b/middle_end/flambda2/parser/fexpr_to_flambda.ml index b2d59f96a11..f839921006d 100644 --- a/middle_end/flambda2/parser/fexpr_to_flambda.ml +++ b/middle_end/flambda2/parser/fexpr_to_flambda.ml @@ -283,7 +283,8 @@ let value_kind_with_subkind_opt : | Some kind -> value_kind_with_subkind kind | None -> Flambda_kind.With_subkind.any_value -let arity a = Flambda_arity.create (List.map value_kind_with_subkind a) +let arity a = + Flambda_arity.create_singletons (List.map value_kind_with_subkind a) let const (c : Fexpr.const) : Reg_width_const.t = match c with @@ -799,11 +800,12 @@ let rec expr env (e : Fexpr.expr) : Flambda.Expr.t = (fun ({ kind; _ } : Fexpr.kinded_parameter) -> value_kind_with_subkind_opt kind) params_and_body.params - |> Flambda_arity.create + |> Flambda_arity.create_singletons in let result_arity = match ret_arity with - | None -> Flambda_arity.create [Flambda_kind.With_subkind.any_value] + | None -> + Flambda_arity.create_singletons [Flambda_kind.With_subkind.any_value] | Some ar -> arity ar in let ( _params, @@ -835,7 +837,7 @@ let rec expr env (e : Fexpr.expr) : Flambda.Expr.t = let my_depth, env = fresh_var env depth_var in let return_continuation, env = fresh_cont env ret_cont ~sort:Return - ~arity:(Flambda_arity.cardinal result_arity) + ~arity:(Flambda_arity.cardinal_unarized result_arity) in let exn_continuation, env = fresh_exn_cont env exn_cont in assert ( @@ -919,12 +921,13 @@ let rec expr env (e : Fexpr.expr) : Flambda.Expr.t = let params_arity = (* CR mshinwell: This needs fixing to cope with the fact that the arities have moved onto [Apply_expr] *) - Flambda_arity.create + Flambda_arity.create_singletons (List.map (fun _ -> Flambda_kind.With_subkind.any_value) args) in let return_arity = match arities with - | None -> Flambda_arity.create [Flambda_kind.With_subkind.any_value] + | None -> + Flambda_arity.create_singletons [Flambda_kind.With_subkind.any_value] | Some { ret_arity; _ } -> arity ret_arity in let alloc = alloc_mode_for_types alloc in @@ -942,13 +945,13 @@ let rec expr env (e : Fexpr.expr) : Flambda.Expr.t = let params_arity = (* CR mshinwell: This needs fixing to cope with the fact that the arities have moved onto [Apply_expr] *) - Flambda_arity.create + Flambda_arity.create_singletons (List.map (fun _ -> Flambda_kind.With_subkind.any_value) args) in let return_arity = (* CR mshinwell: This needs fixing to cope with the fact that the arities have moved onto [Apply_expr] *) - Flambda_arity.create [Flambda_kind.With_subkind.any_value] + Flambda_arity.create_singletons [Flambda_kind.With_subkind.any_value] in ( Call_kind.indirect_function_call_unknown_arity alloc, params_arity, diff --git a/middle_end/flambda2/parser/flambda_to_fexpr.ml b/middle_end/flambda2/parser/flambda_to_fexpr.ml index e0473c1d8e4..71bf5fa83c5 100644 --- a/middle_end/flambda2/parser/flambda_to_fexpr.ml +++ b/middle_end/flambda2/parser/flambda_to_fexpr.ml @@ -452,15 +452,16 @@ let kind_with_subkind_opt (k : Flambda_kind.With_subkind.t) : Fexpr.kind_with_subkind option = if is_default_kind_with_subkind k then None else Some (k |> kind_with_subkind) -let is_default_arity (a : Flambda_arity.t) = - match Flambda_arity.to_list a with +let is_default_arity (a : _ Flambda_arity.t) = + match Flambda_arity.unarize a with | [k] -> is_default_kind_with_subkind k | _ -> false -let arity (a : Flambda_arity.t) : Fexpr.arity = - Flambda_arity.to_list a |> List.map kind_with_subkind +let arity (a : _ Flambda_arity.t) : Fexpr.arity = + (* CR mshinwell: add unboxed arities to Fexpr *) + Flambda_arity.unarize a |> List.map kind_with_subkind -let arity_opt (a : Flambda_arity.t) : Fexpr.arity option = +let arity_opt (a : _ Flambda_arity.t) : Fexpr.arity option = if is_default_arity a then None else Some (arity a) let kinded_parameter env (kp : Bound_parameter.t) : diff --git a/middle_end/flambda2/simplify/apply_cont_rewrite.ml b/middle_end/flambda2/simplify/apply_cont_rewrite.ml index 9d77810f3b0..49933b48cac 100644 --- a/middle_end/flambda2/simplify/apply_cont_rewrite.ml +++ b/middle_end/flambda2/simplify/apply_cont_rewrite.ml @@ -84,7 +84,7 @@ let create ~original_params ~extra_params_and_args ~decide_param_usage = extra_params } -let original_params_arity t = Bound_parameters.arity t.original_params +(* let original_params_arity t = Bound_parameters.arity t.original_params *) let rec partition_used l usage = match l, usage with @@ -234,16 +234,14 @@ let make_rewrite rewrite ~ctx id args = let rewrite_exn_continuation rewrite id exn_cont = let exn_cont_arity = Exn_continuation.arity exn_cont in - if not - (Flambda_arity.equal_ignoring_subkinds exn_cont_arity - (original_params_arity rewrite)) - then - Misc.fatal_errorf - "Arity of exception continuation %a does not match@ [original_params] \ - (%a)" - Exn_continuation.print exn_cont Bound_parameters.print - rewrite.original_params; - assert (Flambda_arity.cardinal exn_cont_arity >= 1); + (* XXX see comment elsewhere - propagating original arity is tedious + + if not (Flambda_arity.equal_ignoring_subkinds exn_cont_arity + (original_params_arity rewrite)) then Misc.fatal_errorf "Arity of exception + continuation %a does not match@ [original_params] \ (%a)" + Exn_continuation.print exn_cont Bound_parameters.print + rewrite.original_params; *) + assert (Flambda_arity.cardinal_unarized exn_cont_arity >= 1); if List.hd rewrite.original_params_usage <> Used then Misc.fatal_errorf diff --git a/middle_end/flambda2/simplify/apply_cont_rewrite.mli b/middle_end/flambda2/simplify/apply_cont_rewrite.mli index f188d475cdd..a29f0dd824a 100644 --- a/middle_end/flambda2/simplify/apply_cont_rewrite.mli +++ b/middle_end/flambda2/simplify/apply_cont_rewrite.mli @@ -42,7 +42,7 @@ val get_used_params : t -> Bound_parameters.t * Bound_parameters.t val get_unused_params : t -> Bound_parameters.t -val original_params_arity : t -> Flambda_arity.t +(* val original_params_arity : t -> Flambda_arity.t *) type rewrite_apply_cont_ctx = | Apply_cont diff --git a/middle_end/flambda2/simplify/continuation_in_env.ml b/middle_end/flambda2/simplify/continuation_in_env.ml index 664e1360cf7..dae49153e5a 100644 --- a/middle_end/flambda2/simplify/continuation_in_env.ml +++ b/middle_end/flambda2/simplify/continuation_in_env.ml @@ -22,10 +22,10 @@ type t = cost_metrics_of_handler : Cost_metrics.t } | Non_inlinable_zero_arity of { handler : Rebuilt_expr.t Or_unknown.t } - | Non_inlinable_non_zero_arity of { arity : Flambda_arity.t } + | Non_inlinable_non_zero_arity of { arity : [`Unarized] Flambda_arity.t } | Toplevel_or_function_return_or_exn_continuation of - { arity : Flambda_arity.t } - | Invalid of { arity : Flambda_arity.t } + { arity : [`Unarized] Flambda_arity.t } + | Invalid of { arity : [`Unarized] Flambda_arity.t } let [@ocamlformat "disable"] print are_rebuilding_terms ppf t = match t with diff --git a/middle_end/flambda2/simplify/continuation_in_env.mli b/middle_end/flambda2/simplify/continuation_in_env.mli index 5e1410886f9..31fe2fd64af 100644 --- a/middle_end/flambda2/simplify/continuation_in_env.mli +++ b/middle_end/flambda2/simplify/continuation_in_env.mli @@ -30,13 +30,13 @@ type t = (** The handler, if available, is stored for [Simplify_switch_expr]. *) } - | Non_inlinable_non_zero_arity of { arity : Flambda_arity.t } + | Non_inlinable_non_zero_arity of { arity : [`Unarized] Flambda_arity.t } | Toplevel_or_function_return_or_exn_continuation of - { arity : Flambda_arity.t } - | Invalid of { arity : Flambda_arity.t } + { arity : [`Unarized] Flambda_arity.t } + | Invalid of { arity : [`Unarized] Flambda_arity.t } (** [Invalid] means that the code of the continuation handler is invalid, not that the continuation has zero uses. *) val print : Are_rebuilding_terms.t -> Format.formatter -> t -> unit -val arity : t -> Flambda_arity.t +val arity : t -> [`Unarized] Flambda_arity.t diff --git a/middle_end/flambda2/simplify/env/continuation_uses.ml b/middle_end/flambda2/simplify/env/continuation_uses.ml index 751760edb8b..e6b6bb0ecd1 100644 --- a/middle_end/flambda2/simplify/env/continuation_uses.ml +++ b/middle_end/flambda2/simplify/env/continuation_uses.ml @@ -20,7 +20,7 @@ module U = One_continuation_use type t = { continuation : Continuation.t; - arity : Flambda_arity.t; + arity : [`Unarized] Flambda_arity.t; uses : U.t list } @@ -95,7 +95,7 @@ let add_uses_to_arg_maps arg_maps uses = let empty_arg_maps arity : arg_types_by_use_id = List.map (fun _ -> Apply_cont_rewrite_id.Map.empty) - (Flambda_arity.to_list arity) + (Flambda_arity.unarize arity) let get_arg_types_by_use_id t = add_uses_to_arg_maps (empty_arg_maps t.arity) t.uses @@ -107,10 +107,12 @@ let get_arg_types_by_use_id_for_invariant_params arity l = List.fold_left (fun arg_maps t -> if not - (Misc.Stdlib.List.is_prefix - ~equal:Flambda_kind.With_subkind.equal_ignoring_subkind - (Flambda_arity.to_list arity) - ~of_:(Flambda_arity.to_list t.arity)) + (Misc.Stdlib.List.is_prefix ~equal:Flambda_kind.equal + (Flambda_arity.unarize arity + |> List.map Flambda_kind.With_subkind.kind) + ~of_: + (Flambda_arity.unarize t.arity + |> List.map Flambda_kind.With_subkind.kind)) then Misc.fatal_errorf "Arity of invariant params@ (%a) is not a prefix of the arity of the \ diff --git a/middle_end/flambda2/simplify/env/continuation_uses.mli b/middle_end/flambda2/simplify/env/continuation_uses.mli index d92e7b3d028..7af4f7591b6 100644 --- a/middle_end/flambda2/simplify/env/continuation_uses.mli +++ b/middle_end/flambda2/simplify/env/continuation_uses.mli @@ -21,7 +21,7 @@ type t -val create : Continuation.t -> Flambda_arity.t -> t +val create : Continuation.t -> [`Unarized] Flambda_arity.t -> t val print : Format.formatter -> t -> unit @@ -50,13 +50,13 @@ val get_arg_types_by_use_id : t -> arg_types_by_use_id prefix of each of these argument lists, corresponding to the invariant params, and merges them. *) val get_arg_types_by_use_id_for_invariant_params : - Flambda_arity.t -> t list -> arg_types_by_use_id + [`Unarized] Flambda_arity.t -> t list -> arg_types_by_use_id val get_use_ids : t -> Apply_cont_rewrite_id.Set.t val number_of_uses : t -> int -val arity : t -> Flambda_arity.t +val arity : t -> [`Unarized] Flambda_arity.t val get_typing_env_no_more_than_one_use : t -> Flambda2_types.Typing_env.t option diff --git a/middle_end/flambda2/simplify/env/upwards_env.mli b/middle_end/flambda2/simplify/env/upwards_env.mli index c23158e38ef..be858282962 100644 --- a/middle_end/flambda2/simplify/env/upwards_env.mli +++ b/middle_end/flambda2/simplify/env/upwards_env.mli @@ -29,10 +29,15 @@ val add_non_inlinable_continuation : handler:Rebuilt_expr.t Or_unknown.t -> t -val add_invalid_continuation : t -> Continuation.t -> Flambda_arity.t -> t +val add_invalid_continuation : + t -> Continuation.t -> [`Unarized] Flambda_arity.t -> t val add_continuation_alias : - t -> Continuation.t -> Flambda_arity.t -> alias_for:Continuation.t -> t + t -> + Continuation.t -> + [`Unarized] Flambda_arity.t -> + alias_for:Continuation.t -> + t val add_linearly_used_inlinable_continuation : t -> @@ -44,7 +49,7 @@ val add_linearly_used_inlinable_continuation : t val add_function_return_or_exn_continuation : - t -> Continuation.t -> Flambda_arity.t -> t + t -> Continuation.t -> [`Unarized] Flambda_arity.t -> t val find_continuation : t -> Continuation.t -> Continuation_in_env.t diff --git a/middle_end/flambda2/simplify/expr_builder.ml b/middle_end/flambda2/simplify/expr_builder.ml index 10895261ed0..18a7d054906 100644 --- a/middle_end/flambda2/simplify/expr_builder.ml +++ b/middle_end/flambda2/simplify/expr_builder.ml @@ -708,14 +708,15 @@ let rewrite_fixed_arity_continuation0 uacc cont_or_apply_cont ~use_id arity : match UE.find_apply_cont_rewrite uenv original_cont with | None -> This_continuation cont | Some rewrite when Apply_cont_rewrite.does_nothing rewrite -> - let arity_in_rewrite = Apply_cont_rewrite.original_params_arity rewrite in - if not (Flambda_arity.equal_ignoring_subkinds arity arity_in_rewrite) - then - Misc.fatal_errorf - "Arity %a provided to fixed-arity-wrapper addition function does not \ - match arity %a in rewrite:@ %a" - Flambda_arity.print arity Flambda_arity.print arity_in_rewrite - Apply_cont_rewrite.print rewrite; + (* XXX getting original_params_arity is tedious as it requires propagation + through Simplify_let_cont + + let arity_in_rewrite = Apply_cont_rewrite.original_params_arity rewrite + in if not (Flambda_arity.equal_ignoring_subkinds arity arity_in_rewrite) + then Misc.fatal_errorf "Arity %a provided to fixed-arity-wrapper addition + function does not \ match arity %a in rewrite:@ %a" Flambda_arity.print + arity Flambda_arity.print arity_in_rewrite Apply_cont_rewrite.print + rewrite; *) This_continuation cont | Some rewrite -> ( let new_wrapper params expr ~free_names @@ -743,9 +744,9 @@ let rewrite_fixed_arity_continuation0 uacc cont_or_apply_cont ~use_id arity : let params = List.map (fun _kind -> Variable.create "param") - (Flambda_arity.to_list arity) + (Flambda_arity.unarize arity) in - let params = List.map2 BP.create params (Flambda_arity.to_list arity) in + let params = List.map2 BP.create params (Flambda_arity.unarize arity) in let args = List.map BP.simple params in let params = Bound_parameters.create params in let apply_cont = Apply_cont.create cont ~args ~dbg:Debuginfo.none in diff --git a/middle_end/flambda2/simplify/expr_builder.mli b/middle_end/flambda2/simplify/expr_builder.mli index 2411e0786a0..1746bb8b512 100644 --- a/middle_end/flambda2/simplify/expr_builder.mli +++ b/middle_end/flambda2/simplify/expr_builder.mli @@ -133,13 +133,13 @@ val rewrite_switch_arm : Upwards_acc.t -> Apply_cont.t -> use_id:Apply_cont_rewrite_id.t -> - Flambda_arity.t -> + [`Unarized] Flambda_arity.t -> rewrite_switch_arm_result val rewrite_fixed_arity_apply : Upwards_acc.t -> use_id:Apply_cont_rewrite_id.t -> - Flambda_arity.t -> + [`Unarized] Flambda_arity.t -> Apply.t -> Upwards_acc.t * Rebuilt_expr.t diff --git a/middle_end/flambda2/simplify/flow/flow.mli b/middle_end/flambda2/simplify/flow/flow.mli index dff6a1b882d..6584d1c37db 100644 --- a/middle_end/flambda2/simplify/flow/flow.mli +++ b/middle_end/flambda2/simplify/flow/flow.mli @@ -82,7 +82,7 @@ module Acc : sig val add_apply_conts : result_cont:(Apply_cont_rewrite_id.t * Continuation.t) option -> exn_cont:Apply_cont_rewrite_id.t * Exn_continuation.t -> - result_arity:Flambda_arity.t -> + result_arity:[`Unarized] Flambda_arity.t -> t -> t diff --git a/middle_end/flambda2/simplify/flow/flow_acc.ml b/middle_end/flambda2/simplify/flow/flow_acc.ml index b205dbc2799..9d09ad470c6 100644 --- a/middle_end/flambda2/simplify/flow/flow_acc.ml +++ b/middle_end/flambda2/simplify/flow/flow_acc.ml @@ -277,7 +277,7 @@ let add_apply_conts ~result_cont ~exn_cont ~result_arity t = | None -> apply_cont_args | Some (rewrite_id, result_cont) -> add_func_result result_cont rewrite_id - ~result_arity:(Flambda_arity.cardinal result_arity) + ~result_arity:(Flambda_arity.cardinal_unarized result_arity) ~extra_args:[] apply_cont_args in { elt with apply_cont_args }) diff --git a/middle_end/flambda2/simplify/flow/flow_acc.mli b/middle_end/flambda2/simplify/flow/flow_acc.mli index 53cec19ac56..ee0ce5ca39d 100644 --- a/middle_end/flambda2/simplify/flow/flow_acc.mli +++ b/middle_end/flambda2/simplify/flow/flow_acc.mli @@ -97,7 +97,7 @@ val add_used_in_current_handler : Name_occurrences.t -> t -> t val add_apply_conts : result_cont:(Apply_cont_rewrite_id.t * Continuation.t) option -> exn_cont:Apply_cont_rewrite_id.t * Exn_continuation.t -> - result_arity:Flambda_arity.t -> + result_arity:[`Unarized] Flambda_arity.t -> t -> t diff --git a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml index 84287423960..85b46ce8172 100644 --- a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml +++ b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml @@ -108,14 +108,15 @@ let speculative_inlining dacc ~apply ~function_type ~simplify_expr ~return_arity UE.add_function_return_or_exn_continuation (UE.create (DA.are_rebuilding_terms dacc)) (Exn_continuation.exn_handler exn_continuation) - (Flambda_arity.create [Flambda_kind.With_subkind.any_value]) + (Flambda_arity.create_singletons + [Flambda_kind.With_subkind.any_value]) in let uenv = match Apply.continuation apply with | Never_returns -> uenv | Return return_continuation -> UE.add_function_return_or_exn_continuation uenv return_continuation - return_arity + (Flambda_arity.unarize_t return_arity) in let uacc = UA.create ~flow_result ~compute_slot_offsets:false uenv dacc diff --git a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli index 1cbaba44152..138118521a9 100644 --- a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli +++ b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli @@ -21,7 +21,7 @@ val make_decision : simplify_expr:Expr.t Simplify_common.expr_simplifier -> function_type:Flambda2_types.Function_type.t -> apply:Apply.t -> - return_arity:Flambda_arity.t -> + return_arity:_ Flambda_arity.t -> Call_site_inlining_decision_type.t val get_rec_info : diff --git a/middle_end/flambda2/simplify/simplify.ml b/middle_end/flambda2/simplify/simplify.ml index 795c1338fab..8a2b8528e7a 100644 --- a/middle_end/flambda2/simplify/simplify.ml +++ b/middle_end/flambda2/simplify/simplify.ml @@ -43,7 +43,7 @@ let run ~cmx_loader ~round unit = let dacc = DA.create denv Continuation_uses_env.empty in let body, uacc = Simplify_expr.simplify_toplevel dacc (FU.body unit) ~return_continuation - ~return_arity:(Flambda_arity.create [K.With_subkind.any_value]) + ~return_arity:(Flambda_arity.create_singletons [K.With_subkind.any_value]) ~exn_continuation in let body = Rebuilt_expr.to_expr body (UA.are_rebuilding_terms uacc) in diff --git a/middle_end/flambda2/simplify/simplify_apply_expr.ml b/middle_end/flambda2/simplify/simplify_apply_expr.ml index 02579724c8b..35492c5ee3c 100644 --- a/middle_end/flambda2/simplify/simplify_apply_expr.ml +++ b/middle_end/flambda2/simplify/simplify_apply_expr.ml @@ -83,7 +83,8 @@ let simplify_direct_tuple_application ~simplify_expr dacc apply ~down_to_up = let dbg = Apply.dbg apply in let n = - Flambda_arity.cardinal (Code_metadata.params_arity callee's_code_metadata) + Flambda_arity.cardinal_unarized + (Code_metadata.params_arity callee's_code_metadata) in (* Split the tuple argument from other potential over application arguments *) let tuple, over_application_args = @@ -92,7 +93,7 @@ let simplify_direct_tuple_application ~simplify_expr dacc apply | _ -> Misc.fatal_errorf "Empty argument list for direct application" in let over_application_arity = - List.tl (Flambda_arity.to_list (Apply.args_arity apply)) + List.tl (Flambda_arity.unarize (Apply.args_arity apply)) in (* Create the list of variables and projections *) let vars_and_fields = @@ -106,7 +107,7 @@ let simplify_direct_tuple_application ~simplify_expr dacc apply let args_arity = (* The components of the tuple must always be of kind [Value] (in Lambda, [layout_field]). *) - Flambda_arity.create + Flambda_arity.create_singletons (List.init n (fun _ -> K.With_subkind.any_value) @ over_application_arity) in @@ -164,7 +165,9 @@ let rebuild_non_inlined_direct_full_application apply ~use_id ~exn_cont_use_id in uacc, RE.create_apply (UA.are_rebuilding_terms uacc) apply | Some use_id -> - EB.rewrite_fixed_arity_apply uacc ~use_id result_arity apply + EB.rewrite_fixed_arity_apply uacc ~use_id + (Flambda_arity.unarize_t result_arity) + apply in after_rebuild expr uacc @@ -236,7 +239,7 @@ let simplify_direct_full_application ~simplify_expr dacc apply function_type | Return apply_return_continuation, Ok result_types -> Result_types.pattern_match result_types ~f:(fun ~params ~results env_extension -> - if Flambda_arity.cardinal params_arity + if Flambda_arity.cardinal_unarized params_arity <> Bound_parameters.cardinal params then Misc.fatal_errorf @@ -244,7 +247,7 @@ let simplify_direct_full_application ~simplify_expr dacc apply function_type types structure:@ %a@ for application:@ %a" Flambda_arity.print params_arity Result_types.print result_types Apply.print apply; - if Flambda_arity.cardinal result_arity + if Flambda_arity.cardinal_unarized result_arity <> Bound_parameters.cardinal results then Misc.fatal_errorf @@ -270,7 +273,7 @@ let simplify_direct_full_application ~simplify_expr dacc apply function_type arg)) denv params args in - let result_arity = Flambda_arity.to_list result_arity in + let result_arity = Flambda_arity.unarize result_arity in let denv = List.fold_left2 (fun denv kind result -> @@ -322,9 +325,10 @@ let simplify_direct_full_application ~simplify_expr dacc apply function_type let simplify_direct_partial_application ~simplify_expr dacc apply ~callee's_code_id ~callee's_code_metadata ~callee's_function_slot - ~param_arity ~result_arity ~recursive ~down_to_up ~coming_from_indirect + ~param_arity ~args_arity ~result_arity ~recursive ~down_to_up + ~coming_from_indirect ~(closure_alloc_mode_from_type : Alloc_mode.For_types.t) ~current_region - ~num_trailing_local_params = + ~num_trailing_local_non_unarized_params = (* Partial-applications are converted in full applications. Let's assume that [foo] takes 6 arguments. Then [foo a b c] gets transformed into: @@ -362,14 +366,18 @@ let simplify_direct_partial_application ~simplify_expr dacc apply Inlining_helpers.( inlined_attribute_on_partial_application_msg Unrolled)) | Default_inlined | Hint_inlined -> ()); - let arity = Flambda_arity.cardinal param_arity in - let args_arity = List.length args in - assert (arity > args_arity); - let applied_args, remaining_param_arity = + let num_non_unarized_params = Flambda_arity.num_params param_arity in + let num_non_unarized_args = Flambda_arity.num_params args_arity in + assert (num_non_unarized_params > num_non_unarized_args); + let remaining_param_arity = + Flambda_arity.partially_apply param_arity + ~num_non_unarized_params_provided:(Flambda_arity.num_params args_arity) + in + let applied_unarized_args, _ = Misc.Stdlib.List.map2_prefix (fun arg kind -> arg, kind) args - (Flambda_arity.to_list param_arity) + (Flambda_arity.unarize param_arity) in let wrapper_var = Variable.create "partial_app" in let compilation_unit = Compilation_unit.get_current_exn () in @@ -381,13 +389,17 @@ let simplify_direct_partial_application ~simplify_expr dacc apply (* If the closure has a local suffix, and we've supplied enough args to hit it, then the closure must be local (because the args or closure might be). *) - let num_leading_heap_params = arity - num_trailing_local_params in - if args_arity <= num_leading_heap_params - then Alloc_mode.For_allocations.heap, num_trailing_local_params + let num_leading_heap_non_unarized_params = + num_non_unarized_params - num_trailing_local_non_unarized_params + in + if num_non_unarized_args <= num_leading_heap_non_unarized_params + then Alloc_mode.For_allocations.heap, num_trailing_local_non_unarized_params else - let num_supplied_local_args = args_arity - num_leading_heap_params in + let num_supplied_local_args = + num_non_unarized_args - num_leading_heap_non_unarized_params + in ( Alloc_mode.For_allocations.local ~region:current_region, - num_trailing_local_params - num_supplied_local_args ) + num_trailing_local_non_unarized_params - num_supplied_local_args ) in (match closure_alloc_mode_from_type with | Heap_or_local -> () @@ -427,7 +439,7 @@ let simplify_direct_partial_application ~simplify_expr dacc apply (fun kind -> let param = Variable.create "param" in Bound_parameter.create param kind) - remaining_param_arity + (Flambda_arity.unarize remaining_param_arity) |> Bound_parameters.create in let call_kind = @@ -478,8 +490,8 @@ let simplify_direct_partial_application ~simplify_expr dacc apply let applied_callee = applied_value (Apply.callee apply, K.With_subkind.any_value) in - let applied_args = List.map applied_value applied_args in - let applied_values = applied_callee :: applied_args in + let applied_unarized_args = List.map applied_value applied_unarized_args in + let applied_values = applied_callee :: applied_unarized_args in let my_closure = Variable.create "my_closure" in let my_region = Variable.create "my_region" in let my_depth = Variable.create "my_depth" in @@ -496,7 +508,8 @@ let simplify_direct_partial_application ~simplify_expr dacc apply in let callee = arg applied_callee in let args = - List.map arg applied_args @ Bound_parameters.simples remaining_params + List.map arg applied_unarized_args + @ Bound_parameters.simples remaining_params in let full_application = Apply.create ~callee ~continuation:(Return return_continuation) @@ -570,10 +583,12 @@ let simplify_direct_partial_application ~simplify_expr dacc apply Code.create code_id ~params_and_body ~free_names_of_params_and_body:free_names ~newer_version_of:None ~params_arity:(Bound_parameters.arity remaining_params) - ~num_trailing_local_params ~result_arity ~result_types:Unknown - ~contains_no_escaping_local_allocs ~stub:true ~inline:Default_inline - ~poll_attribute:Default ~check:Check_attribute.Default_check - ~is_a_functor:false ~recursive ~cost_metrics:cost_metrics_of_body + ~num_trailing_local_params + ~result_arity:(Flambda_arity.unarize_t result_arity) + ~result_types:Unknown ~contains_no_escaping_local_allocs ~stub:true + ~inline:Default_inline ~poll_attribute:Default + ~check:Check_attribute.Default_check ~is_a_functor:false ~recursive + ~cost_metrics:cost_metrics_of_body ~inlining_arguments:(DE.inlining_arguments (DA.denv dacc)) ~dbg ~is_tupled:false ~is_my_closure_used: @@ -724,9 +739,9 @@ let simplify_direct_function_call ~simplify_expr dacc apply ~apply_alloc_mode ~current_region ~callee's_code_id ~callee's_code_metadata ~down_to_up else - let args = Apply.args apply in - let provided_num_args = List.length args in - let num_params = Flambda_arity.cardinal params_arity in + let args_arity = Apply.args_arity apply in + let num_params = Flambda_arity.num_params params_arity in + let provided_num_args = Flambda_arity.num_params args_arity in let result_arity_of_application = Apply.return_arity apply in if provided_num_args = num_params then ( @@ -741,7 +756,8 @@ let simplify_direct_function_call ~simplify_expr dacc apply present on the application expression, so all we can do is check that the function being overapplied returns kind Value. *) if not - (Flambda_arity.equal_ignoring_subkinds result_arity + (Flambda_arity.equal_ignoring_subkinds + (Flambda_arity.unarize_t result_arity) result_arity_of_application) then Misc.fatal_errorf @@ -755,7 +771,7 @@ let simplify_direct_function_call ~simplify_expr dacc apply else if provided_num_args > num_params then ( (* See comment above. *) - if not (Flambda_arity.is_singleton_value result_arity) + if not (Flambda_arity.is_one_param_of_kind_value result_arity) then Misc.fatal_errorf "Non-singleton-value return arity for overapplied OCaml function:@ \ @@ -767,7 +783,9 @@ let simplify_direct_function_call ~simplify_expr dacc apply else if provided_num_args > 0 && provided_num_args < num_params then ( (* See comment above. *) - if not (Flambda_arity.is_singleton_value result_arity_of_application) + if not + (Flambda_arity.is_one_param_of_kind_value + result_arity_of_application) then Misc.fatal_errorf "Non-singleton-value return arity for partially-applied OCaml \ @@ -775,9 +793,11 @@ let simplify_direct_function_call ~simplify_expr dacc apply Apply.print apply; simplify_direct_partial_application ~simplify_expr dacc apply ~callee's_code_id ~callee's_code_metadata ~callee's_function_slot - ~param_arity:params_arity ~result_arity ~recursive ~down_to_up - ~coming_from_indirect ~closure_alloc_mode_from_type ~current_region - ~num_trailing_local_params: + ~param_arity:params_arity ~args_arity + ~result_arity:(Flambda_arity.unarize_t result_arity) + ~recursive ~down_to_up ~coming_from_indirect + ~closure_alloc_mode_from_type ~current_region + ~num_trailing_local_non_unarized_params: (Code_metadata.num_trailing_local_params callee's_code_metadata)) else Misc.fatal_errorf @@ -797,7 +817,9 @@ let rebuild_function_call_where_callee's_type_unavailable apply call_kind Unused_because_function_unknown) in let uacc, expr = - EB.rewrite_fixed_arity_apply uacc ~use_id (Apply.return_arity apply) apply + EB.rewrite_fixed_arity_apply uacc ~use_id + (Flambda_arity.unarize_t (Apply.return_arity apply)) + apply in after_rebuild expr uacc @@ -942,7 +964,7 @@ let simplify_apply_shared dacc apply = "Argument kind %a from arity does not match kind from type %a for \ application:@ %a" K.print kind T.print arg_type Apply.print apply) - (Flambda_arity.to_list (Apply.args_arity apply)) + (Flambda_arity.unarize (Apply.args_arity apply)) arg_types; let inlining_state = Inlining_state.meet @@ -973,7 +995,9 @@ let rebuild_method_call apply ~use_id ~exn_cont_use_id uacc ~after_rebuild = apply in let uacc, expr = - EB.rewrite_fixed_arity_apply uacc ~use_id (Apply.return_arity apply) apply + EB.rewrite_fixed_arity_apply uacc ~use_id + (Flambda_arity.unarize_t (Apply.return_arity apply)) + apply in after_rebuild expr uacc @@ -1033,7 +1057,9 @@ let rebuild_c_call apply ~use_id ~exn_cont_use_id ~return_arity uacc let uacc, expr = match use_id with | Some use_id -> - EB.rewrite_fixed_arity_apply uacc ~use_id return_arity apply + EB.rewrite_fixed_arity_apply uacc ~use_id + (Flambda_arity.unarize_t return_arity) + apply | None -> let uacc = UA.add_free_names uacc (Apply.free_names apply) diff --git a/middle_end/flambda2/simplify/simplify_common.ml b/middle_end/flambda2/simplify/simplify_common.ml index 31df021c87f..d1962cffe94 100644 --- a/middle_end/flambda2/simplify/simplify_common.ml +++ b/middle_end/flambda2/simplify/simplify_common.ml @@ -33,7 +33,7 @@ type simplify_toplevel = Downwards_acc.t -> Expr.t -> return_continuation:Continuation.t -> - return_arity:Flambda_arity.t -> + return_arity:[`Unarized] Flambda_arity.t -> exn_continuation:Continuation.t -> Rebuilt_expr.t * Upwards_acc.t @@ -41,7 +41,7 @@ type simplify_function_body = Downwards_acc.t -> Expr.t -> return_continuation:Continuation.t -> - return_arity:Flambda_arity.t -> + return_arity:[`Unarized] Flambda_arity.t -> exn_continuation:Continuation.t -> loopify_state:Loopify_state.t -> params:Bound_parameters.t -> @@ -96,15 +96,26 @@ let split_direct_over_application apply let callee's_params_arity = Code_metadata.params_arity callee's_code_metadata in - let arity = Flambda_arity.cardinal callee's_params_arity in + let num_non_unarized_params = + Flambda_arity.num_params callee's_params_arity + in + let args_arity = Apply.args_arity apply in + let num_non_unarized_args = Flambda_arity.num_params args_arity in + assert (num_non_unarized_params < num_non_unarized_args); let args = Apply.args apply in - assert (arity < List.length args); - let first_args, remaining_args = Misc.Stdlib.List.split_at arity args in - let _, remaining_arity = - Misc.Stdlib.List.split_at arity - (Apply.args_arity apply |> Flambda_arity.to_list) + let first_args, remaining_args = + Misc.Stdlib.List.split_at + (Flambda_arity.cardinal_unarized callee's_params_arity) + args + in + let remaining_arity = + Flambda_arity.partially_apply args_arity + ~num_non_unarized_params_provided:num_non_unarized_params in - assert (List.compare_lengths remaining_args remaining_arity = 0); + assert ( + List.compare_length_with remaining_args + (Flambda_arity.cardinal_unarized remaining_arity) + = 0); let func_var = Variable.create "full_apply" in let contains_no_escaping_local_allocs = Code_metadata.contains_no_escaping_local_allocs callee's_code_metadata @@ -141,8 +152,7 @@ let split_direct_over_application apply in Apply.create ~callee:(Simple.var func_var) ~continuation (Apply.exn_continuation apply) - ~args:remaining_args - ~args_arity:(Flambda_arity.create remaining_arity) + ~args:remaining_args ~args_arity:remaining_arity ~return_arity:(Apply.return_arity apply) ~call_kind: (Call_kind.indirect_function_call_unknown_arity apply_alloc_mode) @@ -170,7 +180,7 @@ let split_direct_over_application apply List.mapi (fun i kind -> BP.create (Variable.create ("result" ^ string_of_int i)) kind) - (Flambda_arity.to_list (Apply.return_arity apply)) + (Flambda_arity.unarize (Apply.return_arity apply)) in let call_return_continuation, call_return_continuation_free_names = match Apply.continuation apply with @@ -231,7 +241,9 @@ let split_direct_over_application apply ~continuation:(Return after_full_application) (Apply.exn_continuation apply) ~args:first_args ~args_arity:callee's_params_arity - ~return_arity:(Code_metadata.result_arity callee's_code_metadata) + ~return_arity: + (Flambda_arity.unarize_t + (Code_metadata.result_arity callee's_code_metadata)) ~call_kind:(Call_kind.direct_function_call callee's_code_id alloc_mode) (Apply.dbg apply) ~inlined:(Apply.inlined apply) ~inlining_state:(Apply.inlining_state apply) diff --git a/middle_end/flambda2/simplify/simplify_common.mli b/middle_end/flambda2/simplify/simplify_common.mli index 0470bb1c6ec..a9ed859c235 100644 --- a/middle_end/flambda2/simplify/simplify_common.mli +++ b/middle_end/flambda2/simplify/simplify_common.mli @@ -76,7 +76,7 @@ type simplify_toplevel = Downwards_acc.t -> Expr.t -> return_continuation:Continuation.t -> - return_arity:Flambda_arity.t -> + return_arity:[`Unarized] Flambda_arity.t -> exn_continuation:Continuation.t -> Rebuilt_expr.t * Upwards_acc.t @@ -84,7 +84,7 @@ type simplify_function_body = Downwards_acc.t -> Expr.t -> return_continuation:Continuation.t -> - return_arity:Flambda_arity.t -> + return_arity:[`Unarized] Flambda_arity.t -> exn_continuation:Continuation.t -> loopify_state:Loopify_state.t -> params:Bound_parameters.t -> diff --git a/middle_end/flambda2/simplify/simplify_expr.ml b/middle_end/flambda2/simplify/simplify_expr.ml index 5a67c57085e..07259ada94d 100644 --- a/middle_end/flambda2/simplify/simplify_expr.ml +++ b/middle_end/flambda2/simplify/simplify_expr.ml @@ -68,7 +68,7 @@ let simplify_toplevel_common dacc simplify ~params ~implicit_params in let uenv = UE.add_function_return_or_exn_continuation uenv exn_continuation - (Flambda_arity.create [K.With_subkind.any_value]) + (Flambda_arity.create_singletons [K.With_subkind.any_value]) in let uacc = UA.create ~flow_result ~compute_slot_offsets:true uenv dacc diff --git a/middle_end/flambda2/simplify/simplify_set_of_closures.ml b/middle_end/flambda2/simplify/simplify_set_of_closures.ml index feb6d2c5070..6b9bc705102 100644 --- a/middle_end/flambda2/simplify/simplify_set_of_closures.ml +++ b/middle_end/flambda2/simplify/simplify_set_of_closures.ml @@ -175,7 +175,8 @@ let simplify_function_body context ~outer_dacc function_slot_opt assert (not (DE.at_unit_toplevel (DA.denv dacc))); match C.simplify_function_body context dacc body ~return_continuation - ~exn_continuation ~return_arity:(Code.result_arity code) + ~exn_continuation + ~return_arity:(Code.result_arity code |> Flambda_arity.unarize_t) ~implicit_params: (Bound_parameters.create [ Bound_parameter.create my_closure @@ -346,7 +347,7 @@ let simplify_function0 context ~outer_dacc function_slot_opt code_id code BP.create (Variable.create ("result" ^ string_of_int i)) kind_with_subkind) - (Flambda_arity.to_list result_arity) + (Flambda_arity.unarize result_arity) |> Bound_parameters.create in let { params; @@ -739,7 +740,7 @@ let simplify_non_lifted_set_of_closures0 dacc bound_vars ~closure_bound_vars Cost_metrics. { cost_metrics = Code_metadata.cost_metrics code_metadata; params_arity = - Flambda_arity.cardinal (Code_metadata.params_arity code_metadata) + Flambda_arity.num_params (Code_metadata.params_arity code_metadata) } in Simplified_named.create_with_known_free_names ~find_code_characteristics diff --git a/middle_end/flambda2/simplify/simplify_switch_expr.ml b/middle_end/flambda2/simplify/simplify_switch_expr.ml index 0ef1827bd8d..6d19da1c464 100644 --- a/middle_end/flambda2/simplify/simplify_switch_expr.ml +++ b/middle_end/flambda2/simplify/simplify_switch_expr.ml @@ -104,9 +104,9 @@ let rebuild_arm uacc arm (action, use_id, arity, env_at_use) | Non_inlinable_zero_arity { handler = Known handler } -> check_handler ~handler ~action | Non_inlinable_zero_arity { handler = Unknown } -> Some action - | Invalid _ -> None - | Non_inlinable_non_zero_arity _ - | Toplevel_or_function_return_or_exn_continuation _ -> + | Invalid _ | Toplevel_or_function_return_or_exn_continuation _ -> + None + | Non_inlinable_non_zero_arity _ -> Misc.fatal_errorf "Inconsistency for %a between [Apply_cont.is_goto] and \ continuation environment in [UA]:@ %a" @@ -377,7 +377,7 @@ let simplify_arm ~typing_env_at_use ~scrutinee_ty arm action (arms, dacc) = let arity = arg_types |> List.map (fun ty -> K.With_subkind.anything (T.kind ty)) - |> Flambda_arity.create + |> Flambda_arity.create_singletons in let action = Apply_cont.update_args action ~args in let dacc = diff --git a/middle_end/flambda2/simplify_shared/inlining_helpers.ml b/middle_end/flambda2/simplify_shared/inlining_helpers.ml index a1369782303..0f31c9168c7 100644 --- a/middle_end/flambda2/simplify_shared/inlining_helpers.ml +++ b/middle_end/flambda2/simplify_shared/inlining_helpers.ml @@ -72,7 +72,7 @@ let wrap_inlined_body_for_exn_extra_args acc ~extra_args ~apply_exn_continuation let kinded_params = List.map (fun k -> Bound_parameter.create (Variable.create "wrapper_return") k) - (Flambda_arity.to_list result_arity) + (Flambda_arity.unarize result_arity) in let trap_action = Trap_action.Pop { exn_handler = wrapper; raise_kind = None } diff --git a/middle_end/flambda2/simplify_shared/inlining_helpers.mli b/middle_end/flambda2/simplify_shared/inlining_helpers.mli index c1540a75ed5..8f97825168b 100644 --- a/middle_end/flambda2/simplify_shared/inlining_helpers.mli +++ b/middle_end/flambda2/simplify_shared/inlining_helpers.mli @@ -46,7 +46,7 @@ val wrap_inlined_body_for_exn_extra_args : extra_args:(Simple.t * Flambda_kind.With_subkind.t) list -> apply_exn_continuation:Exn_continuation.t -> apply_return_continuation:Flambda.Apply.Result_continuation.t -> - result_arity:Flambda_arity.t -> + result_arity:[`Unarized | `Complex] Flambda_arity.t -> make_inlined_body: ('acc -> apply_exn_continuation:Continuation.t -> diff --git a/middle_end/flambda2/simplify_shared/slot_offsets.ml b/middle_end/flambda2/simplify_shared/slot_offsets.ml index f516398b4e3..6d87dd3d4b8 100644 --- a/middle_end/flambda2/simplify_shared/slot_offsets.ml +++ b/middle_end/flambda2/simplify_shared/slot_offsets.ml @@ -727,7 +727,7 @@ end = struct let module CM = Code_metadata in let is_tupled = CM.is_tupled code_metadata in let params_arity = CM.params_arity code_metadata in - let arity = Flambda_arity.cardinal params_arity in + let arity = Flambda_arity.num_params params_arity in if (arity = 0 || arity = 1) && not is_tupled then 2 else 3 in let s = create_slot ~size (Function_slot function_slot) Unassigned in diff --git a/middle_end/flambda2/terms/apply_expr.ml b/middle_end/flambda2/terms/apply_expr.ml index 35d629cd4ac..2eadecc64c5 100644 --- a/middle_end/flambda2/terms/apply_expr.ml +++ b/middle_end/flambda2/terms/apply_expr.ml @@ -73,8 +73,8 @@ type t = continuation : Result_continuation.t; exn_continuation : Exn_continuation.t; args : Simple.t list; - args_arity : Flambda_arity.t; - return_arity : Flambda_arity.t; + args_arity : [`Unarized | `Complex] Flambda_arity.t; + return_arity : [`Unarized] Flambda_arity.t; call_kind : Call_kind.t; dbg : Debuginfo.t; inlined : Inlined_attribute.t; @@ -158,12 +158,12 @@ let invariant "For [C_call] applications the callee must be directly specified as a \ [Symbol]:@ %a" print t; - match Flambda_arity.to_list return_arity with + match Flambda_arity.unarize return_arity with | [] | [_] -> () | _ :: _ :: _ -> Misc.fatal_errorf "Illegal return arity for C call:@ %a" Flambda_arity.print return_arity)); - if List.compare_lengths args (Flambda_arity.to_list args_arity) <> 0 + if List.compare_lengths args (Flambda_arity.unarize args_arity) <> 0 then Misc.fatal_errorf "Length of argument and arity lists disagree in [Apply]:@ %a" print t diff --git a/middle_end/flambda2/terms/apply_expr.mli b/middle_end/flambda2/terms/apply_expr.mli index ddf9bda1a7a..0eda9561c42 100644 --- a/middle_end/flambda2/terms/apply_expr.mli +++ b/middle_end/flambda2/terms/apply_expr.mli @@ -51,8 +51,8 @@ val create : continuation:Result_continuation.t -> Exn_continuation.t -> args:Simple.t list -> - args_arity:Flambda_arity.t -> - return_arity:Flambda_arity.t -> + args_arity:[`Unarized | `Complex] Flambda_arity.t -> + return_arity:[`Unarized] Flambda_arity.t -> call_kind:Call_kind.t -> Debuginfo.t -> inlined:Inlined_attribute.t -> @@ -77,10 +77,10 @@ val callee : t -> Simple.t val args : t -> Simple.t list (** The arity of the arguments being applied. *) -val args_arity : t -> Flambda_arity.t +val args_arity : t -> [`Unarized | `Complex] Flambda_arity.t (** The arity of the result(s) of the application. *) -val return_arity : t -> Flambda_arity.t +val return_arity : t -> [`Unarized] Flambda_arity.t (** Information about what kind of call is involved (direct function call, method call, etc). *) @@ -110,7 +110,8 @@ val with_continuations : t -> Result_continuation.t -> Exn_continuation.t -> t val with_exn_continuation : t -> Exn_continuation.t -> t (** Change the arguments of an application *) -val with_args : t -> Simple.t list -> args_arity:Flambda_arity.t -> t +val with_args : + t -> Simple.t list -> args_arity:[`Unarized | `Complex] Flambda_arity.t -> t (** Change the call kind of an application. *) val with_call_kind : t -> Call_kind.t -> t diff --git a/middle_end/flambda2/terms/code_metadata.ml b/middle_end/flambda2/terms/code_metadata.ml index 8a8dcab3f14..4a44b597e4e 100644 --- a/middle_end/flambda2/terms/code_metadata.ml +++ b/middle_end/flambda2/terms/code_metadata.ml @@ -17,9 +17,9 @@ type t = { code_id : Code_id.t; newer_version_of : Code_id.t option; - params_arity : Flambda_arity.t; + params_arity : [`Unarized | `Complex] Flambda_arity.t; num_trailing_local_params : int; - result_arity : Flambda_arity.t; + result_arity : [`Unarized | `Complex] Flambda_arity.t; result_types : Result_types.t Or_unknown_or_bottom.t; contains_no_escaping_local_allocs : bool; stub : bool; @@ -58,7 +58,7 @@ module Code_metadata_accessors (X : Metadata_view_type) = struct let num_leading_heap_params t = let { params_arity; num_trailing_local_params; _ } = metadata t in - let n = Flambda_arity.cardinal params_arity - num_trailing_local_params in + let n = Flambda_arity.num_params params_arity - num_trailing_local_params in assert (n >= 0); (* see [create] *) n @@ -124,9 +124,9 @@ include Code_metadata_accessors [@inlined hint] (Metadata_view) type 'a create_type = Code_id.t -> newer_version_of:Code_id.t option -> - params_arity:Flambda_arity.t -> + params_arity:[`Unarized | `Complex] Flambda_arity.t -> num_trailing_local_params:int -> - result_arity:Flambda_arity.t -> + result_arity:[`Unarized | `Complex] Flambda_arity.t -> result_types:Result_types.t Or_unknown_or_bottom.t -> contains_no_escaping_local_allocs:bool -> stub:bool -> @@ -161,7 +161,7 @@ let createk k code_id ~newer_version_of ~params_arity ~num_trailing_local_params | true, (Always_inline | Unroll _) -> Misc.fatal_error "Stubs may not be annotated as [Always_inline] or [Unroll]"); if num_trailing_local_params < 0 - || num_trailing_local_params > Flambda_arity.cardinal params_arity + || num_trailing_local_params > Flambda_arity.cardinal_unarized params_arity then Misc.fatal_errorf "Illegal num_trailing_local_params=%d for params arity: %a" @@ -270,22 +270,22 @@ let [@ocamlformat "disable"] print ppf (if not is_a_functor then Flambda_colours.elide else C.none) is_a_functor Flambda_colours.pop - (if Flambda_arity.is_singleton_value params_arity + (if Flambda_arity.is_one_param_of_kind_value params_arity then Flambda_colours.elide else Flambda_colours.none) Flambda_colours.pop Flambda_arity.print params_arity - (if Flambda_arity.is_singleton_value params_arity + (if Flambda_arity.is_one_param_of_kind_value params_arity then Flambda_colours.elide else Flambda_colours.none) Flambda_colours.pop num_trailing_local_params - (if Flambda_arity.is_singleton_value result_arity + (if Flambda_arity.is_one_param_of_kind_value result_arity then Flambda_colours.elide else Flambda_colours.none) Flambda_colours.pop Flambda_arity.print result_arity - (if Flambda_arity.is_singleton_value result_arity + (if Flambda_arity.is_one_param_of_kind_value result_arity then Flambda_colours.elide else Flambda_colours.none) Flambda_colours.pop diff --git a/middle_end/flambda2/terms/code_metadata.mli b/middle_end/flambda2/terms/code_metadata.mli index 916657b1ab3..d3f5aceb9be 100644 --- a/middle_end/flambda2/terms/code_metadata.mli +++ b/middle_end/flambda2/terms/code_metadata.mli @@ -31,13 +31,14 @@ module type Code_metadata_accessors_result_type = sig val newer_version_of : 'a t -> Code_id.t option - val params_arity : 'a t -> Flambda_arity.t + val params_arity : 'a t -> [`Unarized | `Complex] Flambda_arity.t val num_leading_heap_params : 'a t -> int + (* XXX rename to num_trailing_local_non_unarized_params *) val num_trailing_local_params : 'a t -> int - val result_arity : 'a t -> Flambda_arity.t + val result_arity : 'a t -> [`Unarized | `Complex] Flambda_arity.t val result_types : 'a t -> Result_types.t Or_unknown_or_bottom.t @@ -82,9 +83,9 @@ include Code_metadata_accessors_result_type with type 'a t := t type 'a create_type = Code_id.t -> newer_version_of:Code_id.t option -> - params_arity:Flambda_arity.t -> + params_arity:[`Unarized | `Complex] Flambda_arity.t -> num_trailing_local_params:int -> - result_arity:Flambda_arity.t -> + result_arity:[`Unarized | `Complex] Flambda_arity.t -> result_types:Result_types.t Or_unknown_or_bottom.t -> contains_no_escaping_local_allocs:bool -> stub:bool -> diff --git a/middle_end/flambda2/terms/exn_continuation.ml b/middle_end/flambda2/terms/exn_continuation.ml index 1283eb74b51..e41d927ec34 100644 --- a/middle_end/flambda2/terms/exn_continuation.ml +++ b/middle_end/flambda2/terms/exn_continuation.ml @@ -108,7 +108,7 @@ let arity t = let exn_bucket_kind = Flambda_kind.With_subkind.create Flambda_kind.value Anything in - Flambda_arity.create (exn_bucket_kind :: extra_args) + Flambda_arity.create_singletons (exn_bucket_kind :: extra_args) let with_exn_handler t exn_handler = { t with exn_handler } diff --git a/middle_end/flambda2/terms/exn_continuation.mli b/middle_end/flambda2/terms/exn_continuation.mli index 8de74d2bc6d..911a699dd18 100644 --- a/middle_end/flambda2/terms/exn_continuation.mli +++ b/middle_end/flambda2/terms/exn_continuation.mli @@ -46,7 +46,7 @@ val extra_args : t -> (Simple.t * Flambda_kind.With_subkind.t) list (** The arity of the given exception continuation, taking into account both the exception bucket argument and any [extra_args]. *) -val arity : t -> Flambda_arity.t +val arity : t -> [> `Unarized] Flambda_arity.t val with_exn_handler : t -> Continuation.t -> t diff --git a/middle_end/flambda2/to_cmm/to_cmm_env.ml b/middle_end/flambda2/to_cmm/to_cmm_env.ml index 467e18c9970..46b694da2e1 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_env.ml +++ b/middle_end/flambda2/to_cmm/to_cmm_env.ml @@ -360,7 +360,7 @@ let add_exn_handler env k arity = let env = { env with exn_handlers = Continuation.Set.add k env.exn_handlers } in - match Flambda_arity.to_list arity with + match Flambda_arity.unarize arity with | [] -> Misc.fatal_error "Exception handlers must have at least one parameter" | [_] -> env, [] | _ :: extra_args -> diff --git a/middle_end/flambda2/to_cmm/to_cmm_env.mli b/middle_end/flambda2/to_cmm/to_cmm_env.mli index b84e60fafb0..34cce6d8c43 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_env.mli +++ b/middle_end/flambda2/to_cmm/to_cmm_env.mli @@ -325,7 +325,7 @@ val add_inline_cont : val add_exn_handler : t -> Continuation.t -> - Flambda_arity.t -> + [`Unarized] Flambda_arity.t -> t * (Backend_var.t * Flambda_kind.With_subkind.t) list (** Return whether the given continuation has been registered as an exception diff --git a/middle_end/flambda2/to_cmm/to_cmm_expr.ml b/middle_end/flambda2/to_cmm/to_cmm_expr.ml index b92597c14dd..388d13837f7 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_expr.ml +++ b/middle_end/flambda2/to_cmm/to_cmm_expr.ml @@ -108,9 +108,15 @@ let translate_apply0 ~dbg_with_inlined:dbg env res apply = Lambda.Rc_normal | Nontail -> Lambda.Rc_nontail in - let args_arity = Apply.args_arity apply |> Flambda_arity.to_list in + let args_arity = + Apply.args_arity apply |> Flambda_arity.unarize_per_parameter + in let return_arity = Apply.return_arity apply in - let args_ty = List.map C.extended_machtype_of_kind args_arity in + let args_ty = + List.map + (fun kinds -> List.map C.extended_machtype_of_kind kinds |> Array.concat) + args_arity + in let return_ty = C.extended_machtype_of_return_arity return_arity in match Apply.call_kind apply with | Function { function_call = Direct code_id; alloc_mode = _ } -> ( @@ -176,7 +182,7 @@ let translate_apply0 ~dbg_with_inlined:dbg env res apply = in let returns = Apply.returns apply in let wrap = - match Flambda_arity.to_list return_arity with + match Flambda_arity.unarize return_arity with (* Returned int32 values need to be sign_extended because it's not clear whether C code that returns an int32 returns one that is sign extended or not. There is no need to wrap other return arities. Note that @@ -196,7 +202,7 @@ let translate_apply0 ~dbg_with_inlined:dbg env res apply = in let ty_args = List.map C.exttype_of_kind - (Flambda_arity.to_list (Apply.args_arity apply) + (Flambda_arity.unarize (Apply.args_arity apply) |> List.map K.With_subkind.kind) in ( wrap dbg diff --git a/middle_end/flambda2/to_cmm/to_cmm_set_of_closures.ml b/middle_end/flambda2/to_cmm/to_cmm_set_of_closures.ml index afda54dd1fc..d28209484ef 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_set_of_closures.ml +++ b/middle_end/flambda2/to_cmm/to_cmm_set_of_closures.ml @@ -42,10 +42,14 @@ let get_func_decl_params_arity t code_id = cmm_helpers.ml. *) let params_ty = List.map - (fun k -> - C.extended_machtype_of_kind k - |> C.Extended_machtype.change_tagged_int_to_val) - (Flambda_arity.to_list (Code_metadata.params_arity info)) + (fun ks -> + List.map + (fun k -> + C.extended_machtype_of_kind k + |> C.Extended_machtype.change_tagged_int_to_val) + ks + |> Array.concat) + (Flambda_arity.unarize_per_parameter (Code_metadata.params_arity info)) in let result_machtype = C.extended_machtype_of_return_arity (Code_metadata.result_arity info) diff --git a/middle_end/flambda2/to_cmm/to_cmm_shared.ml b/middle_end/flambda2/to_cmm/to_cmm_shared.ml index 9b6a239d885..707d5e414dc 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_shared.ml +++ b/middle_end/flambda2/to_cmm/to_cmm_shared.ml @@ -246,10 +246,11 @@ let make_update env res dbg kind ~symbol var ~index ~prev_updates = in env, res, Some update -let check_arity arity args = Flambda_arity.cardinal arity = List.length args +let check_arity arity args = + Flambda_arity.cardinal_unarized arity = List.length args let extended_machtype_of_return_arity arity = - match Flambda_arity.to_list arity with + match Flambda_arity.unarize arity with | [] -> (* Functions that never return have arity 0. In that case, we use the most restrictive machtype to ensure that the return value of the function is diff --git a/middle_end/flambda2/to_cmm/to_cmm_shared.mli b/middle_end/flambda2/to_cmm/to_cmm_shared.mli index 72fcbcad728..ddfd3cfe6b4 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_shared.mli +++ b/middle_end/flambda2/to_cmm/to_cmm_shared.mli @@ -98,7 +98,7 @@ val make_update : prev_updates:To_cmm_env.expr_with_info option -> To_cmm_env.t * To_cmm_result.t * To_cmm_env.expr_with_info option -val check_arity : Flambda_arity.t -> _ list -> bool +val check_arity : _ Flambda_arity.t -> _ list -> bool val extended_machtype_of_return_arity : - Flambda_arity.t -> Cmm_helpers.Extended_machtype.t + _ Flambda_arity.t -> Cmm_helpers.Extended_machtype.t diff --git a/middle_end/flambda2/types/flambda2_types.mli b/middle_end/flambda2/types/flambda2_types.mli index 783e4096d5a..19fcd258b5a 100644 --- a/middle_end/flambda2/types/flambda2_types.mli +++ b/middle_end/flambda2/types/flambda2_types.mli @@ -23,7 +23,7 @@ type flambda_type = t val print : Format.formatter -> t -> unit -val arity_of_list : t list -> Flambda_arity.t +val arity_of_list : t list -> [`Unarized] Flambda_arity.t val apply_renaming : t -> Renaming.t -> t @@ -515,10 +515,10 @@ val kind : t -> Flambda_kind.t val get_alias_exn : t -> Simple.t (** For each of the kinds in an arity, create an "unknown" type. *) -val unknown_types_from_arity : Flambda_arity.t -> t list +val unknown_types_from_arity : _ Flambda_arity.t -> t list (** For each of the kinds in an arity, create an "bottom" type. *) -val bottom_types_from_arity : Flambda_arity.t -> t list +val bottom_types_from_arity : _ Flambda_arity.t -> t list (** Whether the given type says that a term of that type can never be constructed (in other words, it is [Invalid]). *) diff --git a/middle_end/flambda2/types/grammar/more_type_creators.ml b/middle_end/flambda2/types/grammar/more_type_creators.ml index 298f030fa7b..664bd506f89 100644 --- a/middle_end/flambda2/types/grammar/more_type_creators.ml +++ b/middle_end/flambda2/types/grammar/more_type_creators.ml @@ -275,7 +275,7 @@ let check_equation name ty = Name.print name TG.print ty let arity_of_list ts = - Flambda_arity.create + Flambda_arity.create_singletons (List.map (fun ty -> Flambda_kind.With_subkind.anything (TG.kind ty)) ts) let rec unknown_with_subkind ?(alloc_mode = Alloc_mode.For_types.unknown ()) @@ -328,7 +328,7 @@ let rec unknown_with_subkind ?(alloc_mode = Alloc_mode.For_types.unknown ()) let bottom_with_subkind kind = bottom (Flambda_kind.With_subkind.kind kind) let unknown_types_from_arity arity = - List.map (fun kind -> unknown_with_subkind kind) (Flambda_arity.to_list arity) + List.map (unknown_with_subkind ?alloc_mode:None) (Flambda_arity.unarize arity) let bottom_types_from_arity arity = - List.map bottom_with_subkind (Flambda_arity.to_list arity) + List.map bottom_with_subkind (Flambda_arity.unarize arity) diff --git a/middle_end/flambda2/types/grammar/more_type_creators.mli b/middle_end/flambda2/types/grammar/more_type_creators.mli index 46e6df57046..fc05adaa47c 100644 --- a/middle_end/flambda2/types/grammar/more_type_creators.mli +++ b/middle_end/flambda2/types/grammar/more_type_creators.mli @@ -141,7 +141,7 @@ val is_alias_of_name : Type_grammar.t -> Name.t -> bool val check_equation : Name.t -> Type_grammar.t -> unit -val arity_of_list : Type_grammar.t list -> Flambda_arity.t +val arity_of_list : Type_grammar.t list -> [`Unarized] Flambda_arity.t val unknown_with_subkind : ?alloc_mode:Alloc_mode.For_types.t -> @@ -149,7 +149,7 @@ val unknown_with_subkind : Type_grammar.t (** For each of the kinds in an arity, create an "unknown" type. *) -val unknown_types_from_arity : Flambda_arity.t -> Type_grammar.t list +val unknown_types_from_arity : _ Flambda_arity.t -> Type_grammar.t list (** For each of the kinds in an arity, create an "bottom" type. *) -val bottom_types_from_arity : Flambda_arity.t -> Type_grammar.t list +val bottom_types_from_arity : _ Flambda_arity.t -> Type_grammar.t list diff --git a/middle_end/flambda2/ui/flambda_colours.ml b/middle_end/flambda2/ui/flambda_colours.ml index d4f206afac2..c40731f71ce 100644 --- a/middle_end/flambda2/ui/flambda_colours.ml +++ b/middle_end/flambda2/ui/flambda_colours.ml @@ -102,6 +102,8 @@ let prim_neither ppf = push ~fg:130 ppf let naked_number ppf = push ~fg:70 ppf +let unboxed_product ppf = push ~fg:198 ppf + let tagged_immediate ppf = push ~fg:70 ppf let constructor ppf = push ~fg:69 ppf diff --git a/middle_end/flambda2/ui/flambda_colours.mli b/middle_end/flambda2/ui/flambda_colours.mli index 200bb0eae61..367fcc4b321 100644 --- a/middle_end/flambda2/ui/flambda_colours.mli +++ b/middle_end/flambda2/ui/flambda_colours.mli @@ -92,4 +92,6 @@ val each_file : directive val lambda : directive +val unboxed_product : directive + val without_colours : f:(unit -> 'a) -> 'a diff --git a/middle_end/internal_variable_names.ml b/middle_end/internal_variable_names.ml index 4fb6290a49b..536c9a627ed 100644 --- a/middle_end/internal_variable_names.ml +++ b/middle_end/internal_variable_names.ml @@ -314,6 +314,10 @@ let punbox_int = "Punbox_int" let pbox_int = "Pbox_int" let punbox_int_arg = "Punbox_int_arg" let pbox_int_arg = "Pbox_int_arg" +let pmake_unboxed_product = "Pmake_unboxed_product" +let punboxed_product_field = "Punboxed_product_field" +let pmake_unboxed_product_arg = "Pmake_unboxed_product_arg" +let punboxed_product_field_arg = "Punboxed_product_field_arg" let anon_fn_with_loc (sloc: Lambda.scoped_location) = let loc = Debuginfo.Scoped_location.to_location sloc in @@ -439,6 +443,8 @@ let of_primitive : Lambda.primitive -> string = function | Pbox_int _ -> pbox_int | Parray_of_iarray -> parray_of_iarray | Parray_to_iarray -> parray_to_iarray + | Pmake_unboxed_product _ -> pmake_unboxed_product + | Punboxed_product_field _ -> punboxed_product_field let of_primitive_arg : Lambda.primitive -> string = function | Pbytes_of_string -> pbytes_of_string_arg @@ -553,3 +559,5 @@ let of_primitive_arg : Lambda.primitive -> string = function | Pbox_int _ -> pbox_int_arg | Parray_of_iarray -> parray_of_iarray_arg | Parray_to_iarray -> parray_to_iarray_arg + | Pmake_unboxed_product _ -> pmake_unboxed_product_arg + | Punboxed_product_field _ -> punboxed_product_field_arg diff --git a/middle_end/printclambda.ml b/middle_end/printclambda.ml index 984c31715c9..f69e1c8d257 100644 --- a/middle_end/printclambda.ml +++ b/middle_end/printclambda.ml @@ -60,6 +60,7 @@ let layout (layout : Lambda.layout) = | Punboxed_int Pint32 -> ":unboxed_int32" | Punboxed_int Pint64 -> ":unboxed_int64" | Punboxed_int Pnativeint -> ":unboxed_nativeint" + | Punboxed_product _ -> Misc.fatal_error "TODO" let rec structured_constant ppf = function | Uconst_float x -> fprintf ppf "%F" x diff --git a/ocaml/asmcomp/cmm_helpers.ml b/ocaml/asmcomp/cmm_helpers.ml index 93fdc4bdc83..b3e6d17a37e 100644 --- a/ocaml/asmcomp/cmm_helpers.ml +++ b/ocaml/asmcomp/cmm_helpers.ml @@ -3276,6 +3276,6 @@ let kind_of_layout (layout : Lambda.layout) = | Pvalue Pfloatval -> Boxed_float | Pvalue (Pboxedintval bi) -> Boxed_integer bi | Pvalue (Pgenval | Pintval | Pvariant _ | Parrayval _) - | Ptop | Pbottom | Punboxed_float | Punboxed_int _ -> Any + | Ptop | Pbottom | Punboxed_float | Punboxed_int _ | Punboxed_product _ -> Any let make_tuple l = match l with [e] -> e | _ -> Ctuple l diff --git a/ocaml/asmcomp/cmmgen.ml b/ocaml/asmcomp/cmmgen.ml index 03eb963d864..324684047ce 100644 --- a/ocaml/asmcomp/cmmgen.ml +++ b/ocaml/asmcomp/cmmgen.ml @@ -124,6 +124,7 @@ let get_field env layout ptr n dbg = | Pvalue Pintval | Punboxed_int _ -> Word_int | Pvalue _ -> Word_val | Punboxed_float -> Double + | Punboxed_product _ -> Misc.fatal_error "TBD" | Ptop -> Misc.fatal_errorf "get_field with Ptop: %a" Debuginfo.print_compact dbg | Pbottom -> @@ -1294,6 +1295,7 @@ and transl_let env str (layout : Lambda.layout) id exp transl_body = end | Pvalue kind -> transl_let_value env str kind id exp transl_body + | Punboxed_product _ -> Misc.fatal_error "TBD" and make_catch (kind : Cmm.kind_for_unboxing) ncatch body handler dbg = match body with | Cexit (nexit,[]) when nexit=ncatch -> handler diff --git a/ocaml/bytecomp/bytegen.ml b/ocaml/bytecomp/bytegen.ml index d2268155244..67b83a08a7c 100644 --- a/ocaml/bytecomp/bytegen.ml +++ b/ocaml/bytecomp/bytegen.ml @@ -119,6 +119,7 @@ let preserve_tailcall_for_prim = function | Pmakeblock _ | Pmakefloatblock _ | Pfield _ | Pfield_computed _ | Psetfield _ | Psetfield_computed _ | Pfloatfield _ | Psetfloatfield _ | Pduprecord _ + | Pmake_unboxed_product _ | Punboxed_product_field _ | Pccall _ | Praise _ | Pnot | Pnegint | Paddint | Psubint | Pmulint | Pdivint _ | Pmodint _ | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ | Poffsetint _ | Poffsetref _ | Pintoffloat @@ -539,6 +540,7 @@ let comp_primitive p args = | Pmakefloatblock _ | Pprobe_is_enabled _ | Punbox_float | Pbox_float _ | Punbox_int _ | Pbox_int _ + | Pmake_unboxed_product _ | Punboxed_product_field _ -> fatal_error "Bytegen.comp_primitive" diff --git a/ocaml/lambda/lambda.ml b/ocaml/lambda/lambda.ml index 09029793cbc..692d5b8c873 100644 --- a/ocaml/lambda/lambda.ml +++ b/ocaml/lambda/lambda.ml @@ -147,6 +147,9 @@ type primitive = | Pfloatfield of int * field_read_semantics * alloc_mode | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int + (* Unboxed products *) + | Pmake_unboxed_product of layout list + | Punboxed_product_field of int * layout list (* Force lazy values *) (* External call *) | Pccall of Primitive.description @@ -266,6 +269,7 @@ and layout = | Pvalue of value_kind | Punboxed_float | Punboxed_int of boxed_integer + | Punboxed_product of layout list | Pbottom and block_shape = @@ -334,7 +338,7 @@ let equal_layout x y = | Pbottom, Pbottom -> true | _, _ -> false -let compatible_layout x y = +let rec compatible_layout x y = match x, y with | Pbottom, _ | _, Pbottom -> true @@ -342,9 +346,13 @@ let compatible_layout x y = | Punboxed_float, Punboxed_float -> true | Punboxed_int bi1, Punboxed_int bi2 -> equal_boxed_integer bi1 bi2 + | Punboxed_product layouts1, Punboxed_product layouts2 -> + List.compare_lengths layouts1 layouts2 = 0 + && List.for_all2 compatible_layout layouts1 layouts2 | Ptop, Ptop -> true | Ptop, _ | _, Ptop -> false - | (Pvalue _ | Punboxed_float | Punboxed_int _), _ -> false + | (Pvalue _ | Punboxed_float | Punboxed_int _ | Punboxed_product _), _ -> + false let must_be_value layout = match layout with @@ -632,6 +640,7 @@ let layout_lazy = Pvalue Pgenval let layout_lazy_contents = Pvalue Pgenval let layout_any_value = Pvalue Pgenval let layout_letrec = layout_any_value +let layout_unboxed_product layouts = Punboxed_product layouts (* CR ncourant: use [Ptop] or remove this as soon as possible. *) let layout_top = layout_any_value @@ -1327,6 +1336,7 @@ let primitive_may_allocate : primitive -> alloc_mode option = function | Pfloatfield (_, _, m) -> Some m | Psetfloatfield _ -> None | Pduprecord _ -> Some alloc_heap + | Pmake_unboxed_product _ | Punboxed_product_field _ -> None | Pccall p -> if not p.prim_alloc then None else begin match p.prim_native_repr_res with @@ -1426,6 +1436,8 @@ let primitive_result_layout (p : primitive) = | Pmakeblock _ | Pmakefloatblock _ | Pmakearray _ | Pduprecord _ | Pduparray _ | Pbigarraydim _ | Pobj_dup -> layout_block | Pfield _ | Pfield_computed _ -> layout_field + | Punboxed_product_field _ -> Misc.fatal_error "Not supported" + | Pmake_unboxed_product layouts -> layout_unboxed_product layouts | Pfloatfield _ | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ | Paddfloat _ | Psubfloat _ | Pmulfloat _ | Pdivfloat _ | Pbox_float _ -> layout_float diff --git a/ocaml/lambda/lambda.mli b/ocaml/lambda/lambda.mli index f368fae0720..5934589522c 100644 --- a/ocaml/lambda/lambda.mli +++ b/ocaml/lambda/lambda.mli @@ -95,6 +95,9 @@ type primitive = | Pfloatfield of int * field_read_semantics * alloc_mode | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int + (* Unboxed products *) + | Pmake_unboxed_product of layout list + | Punboxed_product_field of int * (layout list) (* External call *) | Pccall of Primitive.description (* Exceptions *) @@ -227,6 +230,7 @@ and layout = | Pvalue of value_kind | Punboxed_float | Punboxed_int of boxed_integer + | Punboxed_product of layout list | Pbottom and block_shape = @@ -522,6 +526,8 @@ val layout_any_value : layout (* A layout that is Pgenval because it is bound by a letrec *) val layout_letrec : layout +val layout_unboxed_product : layout list -> layout + val layout_top : layout val layout_bottom : layout diff --git a/ocaml/lambda/printlambda.ml b/ocaml/lambda/printlambda.ml index 3cb44d1579c..23e4b76c543 100644 --- a/ocaml/lambda/printlambda.ml +++ b/ocaml/lambda/printlambda.ml @@ -77,6 +77,9 @@ let variant_kind print_contents ppf ~consts ~non_consts = )) non_consts +let unboxed_product_debug () = + match Sys.getenv "DEBUG" with exception Not_found -> false | _ -> true + let rec value_kind ppf = function | Pgenval -> () | Pintval -> fprintf ppf "[int]" @@ -86,8 +89,10 @@ let rec value_kind ppf = function | Pvariant { consts; non_consts; } -> variant_kind value_kind' ppf ~consts ~non_consts +(* CR mshinwell: we need to work out how to fix these printers properly *) + and value_kind' ppf = function - | Pgenval -> fprintf ppf "*" + | Pgenval -> fprintf ppf (if unboxed_product_debug () then "[val]" else "*") | Pintval -> fprintf ppf "[int]" | Pfloatval -> fprintf ppf "[float]" | Parrayval elt_kind -> fprintf ppf "[%sarray]" (array_kind elt_kind) @@ -95,13 +100,18 @@ and value_kind' ppf = function | Pvariant { consts; non_consts; } -> variant_kind value_kind' ppf ~consts ~non_consts -let layout ppf layout = - match layout with - | Pvalue k -> value_kind ppf k +let rec layout ppf layout_ = + match layout_ with + | Pvalue k -> + (if unboxed_product_debug () then value_kind' else value_kind) ppf k | Ptop -> fprintf ppf "[top]" | Pbottom -> fprintf ppf "[bottom]" | Punboxed_float -> fprintf ppf "[unboxed_float]" | Punboxed_int bi -> fprintf ppf "[unboxed_%s]" (boxed_integer_name bi) + | Punboxed_product layouts -> + fprintf ppf "[%a]" + (pp_print_list ~pp_sep:(fun ppf () -> pp_print_string ppf " * ") layout) + layouts let return_kind ppf (mode, kind) = let smode = alloc_mode mode in @@ -117,6 +127,7 @@ let return_kind ppf (mode, kind) = variant_kind value_kind' ppf ~consts ~non_consts | Punboxed_float -> fprintf ppf ": unboxed_float@ " | Punboxed_int bi -> fprintf ppf ": unboxed_%s@ " (boxed_integer_name bi) + | Punboxed_product _ -> fprintf ppf ": %a" layout kind | Ptop -> fprintf ppf ": top@ " | Pbottom -> fprintf ppf ": bottom@ " @@ -291,6 +302,12 @@ let primitive ppf = function in fprintf ppf "setfloatfield%s %i" init n | Pduprecord (rep, size) -> fprintf ppf "duprecord %a %i" record_rep rep size + | Pmake_unboxed_product layouts -> + fprintf ppf "make_unboxed_product [%a]" + (pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf " * ") layout) layouts + | Punboxed_product_field (n, layouts) -> + fprintf ppf "unboxed_product_field %d [%a]" n + (pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf " * ") layout) layouts | Pccall p -> fprintf ppf "%s" p.prim_name | Praise k -> fprintf ppf "%s" (Lambda.raise_kind k) | Psequand -> fprintf ppf "&&" @@ -472,6 +489,8 @@ let name_of_primitive = function | Pfloatfield _ -> "Pfloatfield" | Psetfloatfield _ -> "Psetfloatfield" | Pduprecord _ -> "Pduprecord" + | Pmake_unboxed_product _ -> "Pmake_unboxed_product" + | Punboxed_product_field _ -> "Punboxed_product_field" | Pccall _ -> "Pccall" | Praise _ -> "Praise" | Psequand -> "Psequand" diff --git a/ocaml/lambda/tmc.ml b/ocaml/lambda/tmc.ml index 3d549135740..1669460dc64 100644 --- a/ocaml/lambda/tmc.ml +++ b/ocaml/lambda/tmc.ml @@ -896,6 +896,9 @@ let rec choice ctx t = (* we don't handle all-float records *) | Pmakefloatblock _ + (* nor unboxed products *) + | Pmake_unboxed_product _ | Punboxed_product_field _ + | Pobj_dup | Pobj_magic _ | Pprobe_is_enabled _ diff --git a/ocaml/lambda/translprim.ml b/ocaml/lambda/translprim.ml index 195f2e9f832..ba0bac42184 100644 --- a/ocaml/lambda/translprim.ml +++ b/ocaml/lambda/translprim.ml @@ -93,6 +93,7 @@ type prim = | Identity | Apply of Lambda.region_close * Lambda.layout | Revapply of Lambda.region_close * Lambda.layout + | Void let units_with_used_primitives = Hashtbl.create 7 let add_used_primitive loc env path = @@ -133,6 +134,14 @@ let to_modify_mode ~poly = function | None -> assert false | Some mode -> transl_modify_mode mode +let layout_unboxed_pair_of_values = + Punboxed_product [Pvalue Pgenval; Pvalue Pgenval] + +let two_unboxed_pairs_of_values = + [ layout_unboxed_pair_of_values; + layout_unboxed_pair_of_values; + ] + let lookup_primitive loc poly pos p = let mode = to_alloc_mode ~poly p.prim_native_repr_res in let arg_modes = List.map (to_modify_mode ~poly) p.prim_native_repr_args in @@ -401,6 +410,40 @@ let lookup_primitive loc poly pos p = | "%obj_magic" -> Primitive(Pobj_magic Lambda.layout_any_value, 1) | "%array_to_iarray" -> Primitive (Parray_to_iarray, 1) | "%array_of_iarray" -> Primitive (Parray_of_iarray, 1) + (* unboxed pairs of void *) + | "%make_unboxed_pair_o_o" -> + Primitive(Pmake_unboxed_product [Punboxed_product []; Punboxed_product []], 2) + | "%unboxed_pair_field_0_o_o" -> + Primitive(Punboxed_product_field (0, [Punboxed_product []; Punboxed_product []]), 1) + | "%unboxed_pair_field_1_o_o" -> + Primitive(Punboxed_product_field (1, [Punboxed_product []; Punboxed_product []]), 1) + (* unboxed pairs of values *) + | "%make_unboxed_pair_v_v" -> + Primitive(Pmake_unboxed_product [Pvalue Pgenval; Pvalue Pgenval], 2) + | "%unboxed_pair_field_0_v_v" -> + Primitive(Punboxed_product_field (0, [Pvalue Pgenval; Pvalue Pgenval]), 1) + | "%unboxed_pair_field_1_v_v" -> + Primitive(Punboxed_product_field (1, [Pvalue Pgenval; Pvalue Pgenval]), 1) + (* unboxed pairs of immediates *) + | "%make_unboxed_pair_i_i" -> + Primitive(Pmake_unboxed_product [Pvalue Pintval; Pvalue Pintval], 2) + | "%unboxed_pair_field_0_i_i" -> + Primitive(Punboxed_product_field (0, [Pvalue Pintval; Pvalue Pintval]), 1) + | "%unboxed_pair_field_1_i_i" -> + Primitive(Punboxed_product_field (1, [Pvalue Pintval; Pvalue Pintval]), 1) + (* unboxed pairs of (unboxed pairs of values) *) + | "%make_unboxed_pair_vup_vup" -> + Primitive(Pmake_unboxed_product [layout_unboxed_pair_of_values; layout_unboxed_pair_of_values], 2) + | "%unboxed_pair_field_0_vup_vup" -> + Primitive(Punboxed_product_field (0, two_unboxed_pairs_of_values), 1) + | "%unboxed_pair_field_1_vup_vup" -> + Primitive(Punboxed_product_field (1, two_unboxed_pairs_of_values), 1) + (* unboxed triples (void, int, void) *) + | "%make_unboxed_triple_o_i_o" -> + Primitive(Pmake_unboxed_product [Punboxed_product []; Pvalue Pintval; Punboxed_product []], 3) + (* void is special as the external is declared to have one parameter + but the primitive takes zero arguments *) + | "%void" -> Void | s when String.length s > 0 && s.[0] = '%' -> raise(Error(loc, Unknown_builtin_primitive s)) | _ -> External p @@ -767,6 +810,7 @@ let lambda_of_prim prim_name prim loc args arg_exps = ap_region_close = pos; ap_mode = alloc_heap; } + | Void, _ -> Lprim (Pmake_unboxed_product [], [], loc) | (Raise _ | Raise_with_backtrace | Lazy_force _ | Loc _ | Primitive _ | Sys_argv | Comparison _ | Send _ | Send_self _ | Send_cache _ | Frame_pointers | Identity @@ -795,6 +839,7 @@ let check_primitive_arity loc p = | Frame_pointers -> p.prim_arity = 0 | Identity -> p.prim_arity = 1 | Apply _ | Revapply _ -> p.prim_arity = 2 + | Void -> true in if not ok then raise(Error(loc, Wrong_arity_builtin_primitive p.prim_name)) @@ -882,6 +927,7 @@ let lambda_primitive_needs_event_after = function | Parray_to_iarray | Parray_of_iarray | Pignore | Psetglobal _ | Pgetglobal _ | Pgetpredef _ | Pmakeblock _ | Pmakefloatblock _ + | Pmake_unboxed_product _ | Punboxed_product_field _ | Pfield _ | Pfield_computed _ | Psetfield _ | Psetfield_computed _ | Pfloatfield _ | Psetfloatfield _ | Praise _ | Psequor | Psequand | Pnot | Pnegint | Paddint | Psubint | Pmulint @@ -903,7 +949,7 @@ let primitive_needs_event_after = function lambda_primitive_needs_event_after (comparison_primitive comp knd) | Lazy_force _ | Send _ | Send_self _ | Send_cache _ | Apply _ | Revapply _ -> true - | Raise _ | Raise_with_backtrace | Loc _ | Frame_pointers | Identity -> false + | Raise _ | Raise_with_backtrace | Loc _ | Frame_pointers | Identity | Void -> false let transl_primitive_application loc p env ty mode path exp args arg_exps pos = let prim = diff --git a/ocaml/middle_end/clambda_primitives.ml b/ocaml/middle_end/clambda_primitives.ml index 77e66745305..b0b731993c7 100644 --- a/ocaml/middle_end/clambda_primitives.ml +++ b/ocaml/middle_end/clambda_primitives.ml @@ -150,6 +150,7 @@ and layout = Lambda.layout = | Pvalue of value_kind | Punboxed_float | Punboxed_int of boxed_integer + | Punboxed_product of layout list | Pbottom and block_shape = Lambda.block_shape diff --git a/ocaml/middle_end/clambda_primitives.mli b/ocaml/middle_end/clambda_primitives.mli index e71b17c4c85..5e3ddfd0765 100644 --- a/ocaml/middle_end/clambda_primitives.mli +++ b/ocaml/middle_end/clambda_primitives.mli @@ -153,6 +153,7 @@ and layout = Lambda.layout = | Pvalue of value_kind | Punboxed_float | Punboxed_int of boxed_integer + | Punboxed_product of layout list | Pbottom and block_shape = Lambda.block_shape diff --git a/ocaml/middle_end/closure/closure.ml b/ocaml/middle_end/closure/closure.ml index a4c352d03fc..26f774f8395 100644 --- a/ocaml/middle_end/closure/closure.ml +++ b/ocaml/middle_end/closure/closure.ml @@ -65,6 +65,7 @@ let is_gc_ignorable kind = | Punboxed_int _ -> true | Pvalue Pintval -> true | Pvalue (Pgenval | Pfloatval | Pboxedintval _ | Pvariant _ | Parrayval _) -> false + | Punboxed_product _ -> Misc.fatal_error "TBD" let split_closure_fv kinds fv = List.fold_right (fun id (not_scanned, scanned) -> diff --git a/ocaml/middle_end/convert_primitives.ml b/ocaml/middle_end/convert_primitives.ml index 541af7ecf86..9180f67f359 100644 --- a/ocaml/middle_end/convert_primitives.ml +++ b/ocaml/middle_end/convert_primitives.ml @@ -38,6 +38,8 @@ let convert (prim : Lambda.primitive) : Clambda_primitives.primitive = | Psetfloatfield (field, init_or_assign) -> Psetfloatfield (field, init_or_assign) | Pduprecord (repr, size) -> Pduprecord (repr, size) + | Pmake_unboxed_product _ + | Punboxed_product_field _ -> Misc.fatal_error "TODO" | Pccall prim -> Pccall prim | Praise kind -> Praise kind | Psequand -> Psequand diff --git a/ocaml/middle_end/flambda/closure_offsets.ml b/ocaml/middle_end/flambda/closure_offsets.ml index cfb1791786d..11f071656ec 100644 --- a/ocaml/middle_end/flambda/closure_offsets.ml +++ b/ocaml/middle_end/flambda/closure_offsets.ml @@ -80,7 +80,8 @@ let add_closure_offsets | Punboxed_float -> true | Punboxed_int _ -> true | Pvalue Pintval -> true - | Pvalue _ -> false) + | Pvalue _ -> false + | Punboxed_product _ -> Misc.fatal_error "TODO") free_vars in let free_variable_offsets, free_variable_pos = diff --git a/ocaml/middle_end/flambda/flambda_to_clambda.ml b/ocaml/middle_end/flambda/flambda_to_clambda.ml index 591e91da625..c64c0ab5c7e 100644 --- a/ocaml/middle_end/flambda/flambda_to_clambda.ml +++ b/ocaml/middle_end/flambda/flambda_to_clambda.ml @@ -711,7 +711,8 @@ and to_clambda_set_of_closures t env | Punboxed_float -> true | Punboxed_int _ -> true | Pvalue Pintval -> true - | Pvalue _ -> false) + | Pvalue _ -> false + | Punboxed_product _ -> Misc.fatal_error "TBD") free_vars in let to_closure_args free_vars = diff --git a/ocaml/middle_end/internal_variable_names.ml b/ocaml/middle_end/internal_variable_names.ml index 4fb6290a49b..536c9a627ed 100644 --- a/ocaml/middle_end/internal_variable_names.ml +++ b/ocaml/middle_end/internal_variable_names.ml @@ -314,6 +314,10 @@ let punbox_int = "Punbox_int" let pbox_int = "Pbox_int" let punbox_int_arg = "Punbox_int_arg" let pbox_int_arg = "Pbox_int_arg" +let pmake_unboxed_product = "Pmake_unboxed_product" +let punboxed_product_field = "Punboxed_product_field" +let pmake_unboxed_product_arg = "Pmake_unboxed_product_arg" +let punboxed_product_field_arg = "Punboxed_product_field_arg" let anon_fn_with_loc (sloc: Lambda.scoped_location) = let loc = Debuginfo.Scoped_location.to_location sloc in @@ -439,6 +443,8 @@ let of_primitive : Lambda.primitive -> string = function | Pbox_int _ -> pbox_int | Parray_of_iarray -> parray_of_iarray | Parray_to_iarray -> parray_to_iarray + | Pmake_unboxed_product _ -> pmake_unboxed_product + | Punboxed_product_field _ -> punboxed_product_field let of_primitive_arg : Lambda.primitive -> string = function | Pbytes_of_string -> pbytes_of_string_arg @@ -553,3 +559,5 @@ let of_primitive_arg : Lambda.primitive -> string = function | Pbox_int _ -> pbox_int_arg | Parray_of_iarray -> parray_of_iarray_arg | Parray_to_iarray -> parray_to_iarray_arg + | Pmake_unboxed_product _ -> pmake_unboxed_product_arg + | Punboxed_product_field _ -> punboxed_product_field_arg diff --git a/ocaml/middle_end/printclambda.ml b/ocaml/middle_end/printclambda.ml index 46056115b85..f4ae9064a50 100644 --- a/ocaml/middle_end/printclambda.ml +++ b/ocaml/middle_end/printclambda.ml @@ -60,6 +60,7 @@ let layout (layout : Lambda.layout) = | Punboxed_int Pint32 -> ":unboxed_int32" | Punboxed_int Pint64 -> ":unboxed_int64" | Punboxed_int Pnativeint -> ":unboxed_nativeint" + | Punboxed_product _ -> Misc.fatal_error "TODO" let rec structured_constant ppf = function | Uconst_float x -> fprintf ppf "%F" x diff --git a/ocaml/typing/predef.ml b/ocaml/typing/predef.ml index 70477d2ca62..30b5b1d0161 100644 --- a/ocaml/typing/predef.ml +++ b/ocaml/typing/predef.ml @@ -47,6 +47,9 @@ and ident_lazy_t = ident_create "lazy_t" and ident_string = ident_create "string" and ident_extension_constructor = ident_create "extension_constructor" and ident_floatarray = ident_create "floatarray" +and ident_unboxed_pair = ident_create "unboxed_pair" +and ident_unboxed_triple = ident_create "unboxed_triple" +and ident_real_void = ident_create "void" let path_int = Pident ident_int and path_char = Pident ident_char @@ -66,6 +69,9 @@ and path_lazy_t = Pident ident_lazy_t and path_string = Pident ident_string and path_extension_constructor = Pident ident_extension_constructor and path_floatarray = Pident ident_floatarray +and path_unboxed_pair = Pident ident_unboxed_pair +and path_unboxed_triple = Pident ident_unboxed_triple +and path_void = Pident ident_real_void let type_int = newgenty (Tconstr(path_int, [], ref Mnil)) and type_char = newgenty (Tconstr(path_char, [], ref Mnil)) diff --git a/ocaml/typing/predef.mli b/ocaml/typing/predef.mli index bb779b310af..8c451ea945d 100644 --- a/ocaml/typing/predef.mli +++ b/ocaml/typing/predef.mli @@ -54,6 +54,9 @@ val path_int64: Path.t val path_lazy_t: Path.t val path_extension_constructor: Path.t val path_floatarray: Path.t +val path_unboxed_pair: Path.t +val path_unboxed_triple: Path.t +val path_void: Path.t val path_match_failure: Path.t val path_invalid_argument: Path.t diff --git a/ocaml/typing/typeopt.ml b/ocaml/typing/typeopt.ml index 1978a50b75f..1b6c67c8999 100644 --- a/ocaml/typing/typeopt.ml +++ b/ocaml/typing/typeopt.ml @@ -537,7 +537,7 @@ let value_kind_union (k1 : Lambda.value_kind) (k2 : Lambda.value_kind) = if Lambda.equal_value_kind k1 k2 then k1 else Pgenval -let layout_union l1 l2 = +let rec layout_union l1 l2 = match l1, l2 with | Pbottom, l | l, Pbottom -> l @@ -546,7 +546,11 @@ let layout_union l1 l2 = | Punboxed_float, Punboxed_float -> Punboxed_float | Punboxed_int bi1, Punboxed_int bi2 -> if equal_boxed_integer bi1 bi2 then l1 else Ptop - | (Ptop | Pvalue _ | Punboxed_float | Punboxed_int _), _ -> + | Punboxed_product layouts1, Punboxed_product layouts2 -> + if List.compare_lengths layouts1 layouts2 <> 0 then Ptop + else Punboxed_product (List.map2 layout_union layouts1 layouts2) + | (Ptop | Pvalue _ | Punboxed_float | Punboxed_int _ | Punboxed_product _), + _ -> Ptop (* Error report *) diff --git a/ocaml/utils/misc.mli b/ocaml/utils/misc.mli index a93cc39f5d3..ee860ba0963 100644 --- a/ocaml/utils/misc.mli +++ b/ocaml/utils/misc.mli @@ -99,7 +99,7 @@ module Stdlib : sig (** The lexicographic order supported by the provided order. There is no constraint on the relative lengths of the lists. *) - val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool + val equal : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool (** Returns [true] if and only if the given lists have the same length and content with respect to the given equality function. *) diff --git a/up.ml b/up.ml new file mode 100644 index 00000000000..b5753472e86 --- /dev/null +++ b/up.ml @@ -0,0 +1,291 @@ +external make_unboxed_pair_v_v : 'a -> 'b -> ('a, 'b) unboxed_pair = "%make_unboxed_pair_v_v" +external unboxed_pair_field_0_v_v : ('a, 'b) unboxed_pair -> 'a = "%unboxed_pair_field_0_v_v" +external unboxed_pair_field_1_v_v : ('a, 'b) unboxed_pair -> 'b = "%unboxed_pair_field_1_v_v" + +let f i x y = + let p = make_unboxed_pair_v_v x y in + if i < 0 then unboxed_pair_field_0_v_v p + else unboxed_pair_field_1_v_v p + +external make_unboxed_pair_vup_vup : + ('a, 'b) unboxed_pair -> ('c, 'd) unboxed_pair + -> (('a, 'b) unboxed_pair, ('c, 'd) unboxed_pair) unboxed_pair + = "%make_unboxed_pair_vup_vup" + +external unboxed_pair_field_0_vup_vup : + (('a, 'b) unboxed_pair, _) unboxed_pair + -> ('a, 'b) unboxed_pair = "%unboxed_pair_field_0_vup_vup" + +let g i x y = + let p = make_unboxed_pair_v_v x y in + let q = make_unboxed_pair_vup_vup p p in + let p_again = unboxed_pair_field_0_vup_vup q in + if i < 0 then unboxed_pair_field_0_v_v p_again + else unboxed_pair_field_1_v_v p_again + +external unboxed_pair_field_1_vup_vup : + (_, ('a, 'b) unboxed_pair) unboxed_pair + -> ('a, 'b) unboxed_pair = "%unboxed_pair_field_1_vup_vup" + +let h i x y = + let p = make_unboxed_pair_v_v x y in + let p' = make_unboxed_pair_v_v y x in + let q = make_unboxed_pair_vup_vup p p' in + let r = + if i < 0 then unboxed_pair_field_0_vup_vup q + else unboxed_pair_field_1_vup_vup q + in + if i < 0 then unboxed_pair_field_0_v_v r + else unboxed_pair_field_1_v_v r + +external make_unboxed_pair_i_i : 'a -> 'b -> ('a, 'b) unboxed_pair = "%make_unboxed_pair_i_i" +external unboxed_pair_field_0_i_i : ('a, 'b) unboxed_pair -> 'a = "%unboxed_pair_field_0_i_i" +external unboxed_pair_field_1_i_i : ('a, 'b) unboxed_pair -> 'b = "%unboxed_pair_field_1_i_i" + +let[@inline never] takes_unboxed_pair (p : (int, int) unboxed_pair) = + let p0 = unboxed_pair_field_0_i_i p in + let p1 = unboxed_pair_field_1_i_i p in + p0 + p1 + +let caller x y = + let p = make_unboxed_pair_i_i x y in + takes_unboxed_pair p + +let[@inline never] takes_two_unboxed_pairs + (p : (int, int) unboxed_pair) + (q : (int, int) unboxed_pair) = + let p0 = unboxed_pair_field_0_i_i p in + let p1 = unboxed_pair_field_1_i_i p in + let q0 = unboxed_pair_field_0_i_i q in + let q1 = unboxed_pair_field_1_i_i q in + p0 + 10*p1 + 100*q0 + 1000*q1 + +let caller2 x y = + let p = make_unboxed_pair_i_i x y in + let q = make_unboxed_pair_i_i y x in + takes_two_unboxed_pairs p q + +let make_partial x y = + let p = make_unboxed_pair_i_i x y in + let partial = takes_two_unboxed_pairs p in + let q = make_unboxed_pair_i_i y x in + (Sys.opaque_identity partial) q + +let () = + Printf.printf "%d\n%!" (make_partial 1 2) + +let[@inline never] takes_three_unboxed_pairs + (p : (int, int) unboxed_pair) + (q : (int, int) unboxed_pair) + (r : (int, int) unboxed_pair) = + let p0 = unboxed_pair_field_0_i_i p in + let p1 = unboxed_pair_field_1_i_i p in + let q0 = unboxed_pair_field_0_i_i q in + let q1 = unboxed_pair_field_1_i_i q in + let r0 = unboxed_pair_field_0_i_i r in + let r1 = unboxed_pair_field_1_i_i r in + p0 + 10*p1 + 100*q0 + 1000*q1 + 10000*r0 + 100000*r1 + +let make_partial3 a b c d e f = + let p = make_unboxed_pair_i_i a b in + let q = make_unboxed_pair_i_i c d in + let r = make_unboxed_pair_i_i e f in + let partial1 = takes_three_unboxed_pairs p in + let partial2 = (Sys.opaque_identity partial1) q in + (Sys.opaque_identity partial2) r + +let () = + Printf.printf "%d\n%!" (make_partial3 1 2 3 4 5 6) + +let[@inline never] returns_unboxed_pair_not_inlined x = + if x < 0 then make_unboxed_pair_i_i x x + else make_unboxed_pair_i_i (x + 1) (x + 2) + +let[@inline] returns_unboxed_pair_inlined x = + if x < 0 then make_unboxed_pair_i_i x x + else make_unboxed_pair_i_i (x + 1) (x + 2) + +let call_function_returning_unboxed_pair x = + let p1 = returns_unboxed_pair_not_inlined x in + let p2 = returns_unboxed_pair_inlined x in + let p1_0 = unboxed_pair_field_0_i_i p1 in + let p1_1 = unboxed_pair_field_1_i_i p1 in + let p2_0 = unboxed_pair_field_0_i_i p2 in + let p2_1 = unboxed_pair_field_1_i_i p2 in + p1_0 + p1_1 + p2_0 + p2_1 + +let () = + Printf.printf "%d\n%!" (call_function_returning_unboxed_pair 42) + +external void : unit -> void = "%void" + +let void_const (v : void) = 42 + +let void0 (v : void) x = x + +let void1a (v : void) x y = x +let void1b (v : void) x y = y + +let void2a x (v : void) y = x +let void2b x (v : void) y = y + +let void3a x y (v : void) = x +let void3b x y (v : void) = y + +let apply_void1a_no_wrapper x y = + let p = (Sys.opaque_identity void1a) (void ()) in + p x y + +let () = + Printf.printf "%d (expected 1)\n%!" (apply_void1a_no_wrapper 1 2) + +let[@inline never] two_voids_const (v : void) (v : void) = 42 +let[@inline never] two_voids_const_side1 (v : void) = + Printf.printf "foo\n%!"; fun (v : void) -> 42 + +let[@inline never] two_voids_const_side2 (v : void) (v : void) = + Printf.printf "bar\n%!"; + 42 + +(* With partial applications concealed from flambda *) +let () = + let p = (Sys.opaque_identity two_voids_const) (void ()) in + Printf.printf "%d (expected 42)\n%!" (p (void ())); + let p = (Sys.opaque_identity two_voids_const_side1) (void ()) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void ())); + let p = (Sys.opaque_identity two_voids_const_side2) (void ()) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void ())) + +(* With partial applications visible to flambda (From_lambda) *) +let () = + let p = Sys.opaque_identity (two_voids_const (void ())) in + Printf.printf "%d (expected 42)\n%!" (p (void ())); + let p = Sys.opaque_identity (two_voids_const_side1 (void ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void ())); + let p = Sys.opaque_identity (two_voids_const_side2 (void ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void ())) + +(* With partial applications visible to flambda (Simplify) *) +let[@inline] to_inline two_voids_const two_voids_const_side1 + two_voids_const_side2 = + let p = Sys.opaque_identity (two_voids_const (void ())) in + Printf.printf "%d (expected 42)\n%!" (p (void ())); + let p = Sys.opaque_identity (two_voids_const_side1 (void ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void ())); + let p = Sys.opaque_identity (two_voids_const_side2 (void ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void ())) + +let () = + to_inline two_voids_const two_voids_const_side1 two_voids_const_side2 + +(* Overapplications concealed from flambda *) +let () = + Printf.printf "OVERAPP1\n%!"; + let x = (Sys.opaque_identity two_voids_const) (void ()) (void ()) in + Printf.printf "%d (expected 42)\n%!" x; + let x = (Sys.opaque_identity two_voids_const_side1) (void ()) (void ()) in + Printf.printf "%d (expected 42)\n%!" x; + let x = (Sys.opaque_identity two_voids_const_side2) (void ()) (void ()) in + Printf.printf "%d (expected 42)\n%!" x + +(* Overapplications visible to flambda *) +let () = + Printf.printf "OVERAPP2\n%!"; + let x = two_voids_const (void ()) (void ()) in + Printf.printf "%d (expected 42)\n%!" x; + let x = two_voids_const_side1 (void ()) (void ()) in + Printf.printf "%d (expected 42)\n%!" x; + let x = two_voids_const_side2 (void ()) (void ()) in + Printf.printf "%d (expected 42)\n%!" x + +(* Overapplications visible to simplify only *) +let[@inline always] g (f : void -> void -> int) : int = f (void ()) (void ()) +let () = + Printf.printf "OVERAPP3\n%!"; + let x = g two_voids_const in + Printf.printf "%d (expected 42)\n%!" x; + let x = g two_voids_const_side1 in + Printf.printf "%d (expected 42)\n%!" x; + let x = g two_voids_const_side2 in + Printf.printf "%d (expected 42)\n%!" x + +(* From above: with partial applications visible to flambda (From_lambda), + but using void arguments extracted from unboxed products *) +external make_unboxed_pair_o_o : void -> void -> (void, void) unboxed_pair = + "%make_unboxed_pair_o_o" +external unboxed_pair_field_0_o_o : (void, void) unboxed_pair -> void = + "%unboxed_pair_field_0_o_o" +external unboxed_pair_field_1_o_o : (void, void) unboxed_pair -> void = + "%unboxed_pair_field_1_o_o" + +let[@inline never] void_from_product () = + let p = make_unboxed_pair_o_o (void ()) (void ()) in + unboxed_pair_field_0_o_o p + +let[@inline] void_from_product_inlined () = + let p = make_unboxed_pair_o_o (void ()) (void ()) in + unboxed_pair_field_0_o_o p + +let () = + let p = Sys.opaque_identity (two_voids_const (void_from_product ())) in + Printf.printf "%d (expected 42)\n%!" (p (void_from_product ())); + let p = Sys.opaque_identity (two_voids_const_side1 (void_from_product ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void_from_product ())); + let p = Sys.opaque_identity (two_voids_const_side2 (void_from_product ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void_from_product ())) + +let () = + let p = Sys.opaque_identity (two_voids_const (void_from_product_inlined ())) in + Printf.printf "%d (expected 42)\n%!" (p (void_from_product_inlined ())); + let p = Sys.opaque_identity (two_voids_const_side1 (void_from_product_inlined ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void_from_product_inlined ())); + let p = Sys.opaque_identity (two_voids_const_side2 (void_from_product_inlined ())) in + Printf.printf "after definition\n%!"; + Printf.printf "%d (expected 42)\n%!" (p (void_from_product_inlined ())) + +(* version without printing to declutter Cmm *) +let[@inline never] returns_unboxed_pair_of_voids_not_inlined0 x = + make_unboxed_pair_o_o (void ()) (void ()) + +let[@inline never] returns_unboxed_pair_of_voids_not_inlined x = + if x < 0 then make_unboxed_pair_o_o (void ()) (void ()) + else ( + Printf.printf "foo\n%!"; + make_unboxed_pair_o_o (void ()) (void ()) + ) + +let[@inline] returns_unboxed_pair_of_voids_inlined x = + if x < 0 then make_unboxed_pair_o_o (void ()) (void ()) + else ( + Printf.printf "foo2\n%!"; + make_unboxed_pair_o_o (void ()) (void ()) + ) + +let print_foo (_ : void) = Printf.printf "FOO\n%!" + +let[@inline never] call_functions_returning_unboxed_pair_of_voids x = + let p1 = returns_unboxed_pair_of_voids_not_inlined x in + let p2 = returns_unboxed_pair_of_voids_inlined x in + print_foo (unboxed_pair_field_0_o_o p1); + print_foo (unboxed_pair_field_1_o_o p1); + print_foo (unboxed_pair_field_0_o_o p2); + print_foo (unboxed_pair_field_1_o_o p2) + +let () = call_functions_returning_unboxed_pair_of_voids 100 +let () = call_functions_returning_unboxed_pair_of_voids (-100) + +external make_unboxed_triple_o_i_o + : void -> int -> void -> (void, int, void) unboxed_triple = + "%make_unboxed_triple_o_i_o" + +let[@inline never] returns_unboxed_triple_of_void_int_void_not_inlined x = + make_unboxed_triple_o_i_o (void ()) x (void ()) From 43a8de4e66d0bb21d589928f8c1d14e2ee4e21e4 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Thu, 11 May 2023 16:15:17 +0200 Subject: [PATCH 08/30] Refactoring for raise --- .../from_lambda/closure_conversion.ml | 11 + .../from_lambda/closure_conversion.mli | 10 + .../flambda2/from_lambda/lambda_to_flambda.ml | 228 ++---------------- ocaml/lambda/lambda.ml | 2 +- 4 files changed, 48 insertions(+), 203 deletions(-) diff --git a/middle_end/flambda2/from_lambda/closure_conversion.ml b/middle_end/flambda2/from_lambda/closure_conversion.ml index f9471694714..43d19dae899 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion.ml @@ -714,6 +714,17 @@ let close_primitive acc env ~let_bound_var named (prim : Lambda.primitive) ~args ~big_endian:(Env.big_endian env) ~register_const0 prim ~args dbg ~current_region k +let close_raise acc env ~raise_kind ~args loc exn_continuation ~current_region = + let prim : Lambda.primitive = Praise raise_kind in + let exn_continuation = Some exn_continuation in + let named : IR.named = + Prim { prim; args; loc; exn_continuation; region = current_region } + in + close_primitive acc env ~let_bound_var:(Variable.create "unused") named prim + ~args loc exn_continuation + ~current_region:(fst (Env.find_var env current_region)) + (fun _acc _named -> assert false (* see above *)) + let close_trap_action_opt trap_action = Option.map (fun (trap_action : IR.trap_action) : Trap_action.t -> diff --git a/middle_end/flambda2/from_lambda/closure_conversion.mli b/middle_end/flambda2/from_lambda/closure_conversion.mli index d0a8937e8af..d2e619ca90a 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.mli +++ b/middle_end/flambda2/from_lambda/closure_conversion.mli @@ -70,6 +70,16 @@ val close_switch : IR.switch -> Expr_with_acc.t +val close_raise : + Acc.t -> + Env.t -> + raise_kind:Lambda.raise_kind -> + args:IR.simple list -> + Lambda.scoped_location -> + IR.exn_continuation -> + current_region:Ident.t -> + Expr_with_acc.t + type 'a close_program_metadata = | Normal : [`Normal] close_program_metadata | Classic : diff --git a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml index 0320cd1c3a5..5e49290914b 100644 --- a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml +++ b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml @@ -1254,101 +1254,6 @@ let primitive_can_raise (prim : Lambda.primitive) = | Punboxed_product_field _ -> false -let primitive_result_kind (prim : Lambda.primitive) : _ Flambda_arity.t = - match prim with - | Pccall { prim_native_repr_res = _, Untagged_int; _ } -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.tagged_immediate] - | Pccall { prim_native_repr_res = _, Unboxed_float; _ } - | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ | Paddfloat _ | Psubfloat _ - | Pmulfloat _ | Pdivfloat _ | Pfloatfield _ - | Parrayrefs Pfloatarray - | Parrayrefu Pfloatarray - | Pbigarrayref (_, _, (Pbigarray_float32 | Pbigarray_float64), _) -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_float] - | Pccall { prim_native_repr_res = _, Unboxed_integer Pnativeint; _ } - | Pbigarrayref (_, _, Pbigarray_native_int, _) -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_nativeint] - | Pccall { prim_native_repr_res = _, Unboxed_integer Pint32; _ } - | Pstring_load_32 _ | Pbytes_load_32 _ | Pbigstring_load_32 _ - | Pbigarrayref (_, _, Pbigarray_int32, _) -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_int32] - | Pccall { prim_native_repr_res = _, Unboxed_integer Pint64; _ } - | Pstring_load_64 _ | Pbytes_load_64 _ | Pbigstring_load_64 _ - | Pbigarrayref (_, _, Pbigarray_int64, _) -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_int64] - | Pnegint | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint - | Plsrint | Pasrint | Pmodint _ | Pdivint _ | Pignore | Psequand | Psequor - | Pnot | Pbytesrefs | Pstringrefs | Pbytessets | Pstring_load_16 _ - | Pbytes_load_16 _ | Pbigstring_load_16 _ | Pbytes_set_16 _ | Pbytes_set_32 _ - | Pbytes_set_64 _ | Pbigstring_set_16 _ | Pbigstring_set_32 _ - | Pbigstring_set_64 _ | Pintcomp _ | Pcompare_ints | Pcompare_floats - | Pcompare_bints _ | Pintoffloat | Pfloatcomp _ | Parraysets _ - | Pbigarrayset _ | Psetfield _ | Psetfield_computed _ | Psetfloatfield _ - | Pstringlength | Pstringrefu | Pbyteslength | Pbytesrefu | Pbytessetu - | Parraylength _ | Parraysetu _ | Pisint _ | Pbintcomp _ | Pintofbint _ - | Pisout - | Parrayrefs Pintarray - | Parrayrefu Pintarray - | Pprobe_is_enabled _ | Pctconst _ | Pbswap16 - | Pbigarrayref - ( _, - _, - ( Pbigarray_sint8 | Pbigarray_uint8 | Pbigarray_sint16 - | Pbigarray_uint16 | Pbigarray_caml_int ), - _ ) -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.tagged_immediate] - | Pdivbint { size = bi; _ } - | Pmodbint { size = bi; _ } - | Pandbint (bi, _) - | Porbint (bi, _) - | Pxorbint (bi, _) - | Plslbint (bi, _) - | Plsrbint (bi, _) - | Pasrbint (bi, _) - | Pnegbint (bi, _) - | Paddbint (bi, _) - | Psubbint (bi, _) - | Pmulbint (bi, _) - | Pbintofint (bi, _) - | Pcvtbint (_, bi, _) - | Pbbswap (bi, _) - | Pbox_int (bi, _) -> - Flambda_arity.create_singletons - [ (match bi with - | Pint32 -> Flambda_kind.With_subkind.boxed_int32 - | Pint64 -> Flambda_kind.With_subkind.boxed_int64 - | Pnativeint -> Flambda_kind.With_subkind.boxed_nativeint) ] - | Popaque layout | Pobj_magic layout -> - Flambda_arity.create_singletons - [Flambda_kind.With_subkind.from_lambda layout] - | Praise _ -> - (* CR ncourant: this should be bottom, but we don't have it *) - Flambda_arity.create_singletons [Flambda_kind.With_subkind.any_value] - | Pccall { prim_native_repr_res = _, Same_as_ocaml_repr; _ } - | Parrayrefs (Pgenarray | Paddrarray) - | Parrayrefu (Pgenarray | Paddrarray) - | Pbytes_to_string | Pbytes_of_string | Parray_of_iarray | Parray_to_iarray - | Pgetglobal _ | Psetglobal _ | Pgetpredef _ | Pmakeblock _ - | Pmakefloatblock _ | Pfield _ | Pfield_computed _ | Pduprecord _ - | Poffsetint _ | Poffsetref _ | Pmakearray _ | Pduparray _ | Pbigarraydim _ - | Pbigarrayref - (_, _, (Pbigarray_complex32 | Pbigarray_complex64 | Pbigarray_unknown), _) - | Pint_as_pointer | Pobj_dup -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.any_value] - | Pbox_float _ -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.boxed_float] - | Punbox_float -> - Flambda_arity.create_singletons [Flambda_kind.With_subkind.naked_float] - | Punbox_int bi -> - Flambda_arity.create_singletons - [ (match bi with - | Pint32 -> Flambda_kind.With_subkind.naked_int32 - | Pint64 -> Flambda_kind.With_subkind.naked_int64 - | Pnativeint -> Flambda_kind.With_subkind.naked_nativeint) ] - | Pmake_unboxed_product _ | Punboxed_product_field _ -> - Misc.fatal_errorf "Primitive not allowed here:@ %a" Printlambda.primitive - prim - type non_tail_continuation = Acc.t -> Env.t -> @@ -1639,116 +1544,35 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) ~current_region:(Env.current_region env) | Dissected lam -> cps acc env ccenv lam k k_exn) | Lprim (prim, args, loc) -> ( - match prim with - | Pmake_unboxed_product _ | Punboxed_product_field _ -> - (* This transformation cannot be done for [Praise] (because of the bottom - layout in Lambda) and is probably less efficient than the normal code - path in the next clause. So for the moment we just do it for the - unboxed product cases, as it simplifies matters. *) - (* CR mshinwell: One note though is that [primitive_result_kind] could be - deleted if we could use a path like this all the time. *) + match[@ocaml.warning "-fragile-match"] prim with + | Praise raise_kind -> + (match args with + | [_] -> () + | [] | _ :: _ -> + Misc.fatal_errorf "Wrong number of arguments for Lraise: %a" + Printlambda.primitive prim); + cps_non_tail_list acc env ccenv args + (fun acc _env ccenv args _arity -> + let exn_continuation : IR.exn_continuation = + { exn_handler = k_exn; + extra_args = extra_args_for_exn_continuation env k_exn + } + in + CC.close_raise acc ccenv ~raise_kind ~args loc exn_continuation + ~current_region:(Env.current_region env)) + k_exn + | _ -> let id = Ident.create_local "prim" in - let result_layout = - match prim with - | Pmake_unboxed_product layouts -> L.Punboxed_product layouts - | Punboxed_product_field (field, layouts) -> - (Array.of_list layouts).(field) - | Pbytes_to_string | Pbytes_of_string | Pignore | Pgetglobal _ - | Psetglobal _ | Pgetpredef _ | Pmakeblock _ | Pmakefloatblock _ - | Pfield _ | Pfield_computed _ | Psetfield _ | Psetfield_computed _ - | Pfloatfield _ | Psetfloatfield _ | Pduprecord _ | Pccall _ | Praise _ - | Psequand | Psequor | Pnot | Pnegint | Paddint | Psubint | Pmulint - | Pdivint _ | Pmodint _ | Pandint | Porint | Pxorint | Plslint | Plsrint - | Pasrint | Pintcomp _ | Pcompare_ints | Pcompare_floats - | Pcompare_bints _ | Poffsetint _ | Poffsetref _ | Pintoffloat - | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ | Paddfloat _ | Psubfloat _ - | Pmulfloat _ | Pdivfloat _ | Pfloatcomp _ | Pstringlength | Pstringrefu - | Pstringrefs | Pbyteslength | Pbytesrefu | Pbytessetu | Pbytesrefs - | Pbytessets | Pmakearray _ | Pduparray _ | Parraylength _ - | Parrayrefu _ | Parraysetu _ | Parrayrefs _ | Parraysets _ | Pisint _ - | Pisout | Pbintofint _ | Pintofbint _ | Pcvtbint _ | Pnegbint _ - | Paddbint _ | Psubbint _ | Pmulbint _ | Pdivbint _ | Pmodbint _ - | Pandbint _ | Porbint _ | Pxorbint _ | Plslbint _ | Plsrbint _ - | Pasrbint _ | Pbintcomp _ | Pbigarrayref _ | Pbigarrayset _ - | Pbigarraydim _ | Pstring_load_16 _ | Pstring_load_32 _ - | Pstring_load_64 _ | Pbytes_load_16 _ | Pbytes_load_32 _ - | Pbytes_load_64 _ | Pbytes_set_16 _ | Pbytes_set_32 _ | Pbytes_set_64 _ - | Pbigstring_load_16 _ | Pbigstring_load_32 _ | Pbigstring_load_64 _ - | Pbigstring_set_16 _ | Pbigstring_set_32 _ | Pbigstring_set_64 _ - | Pctconst _ | Pbswap16 | Pbbswap _ | Pint_as_pointer | Popaque _ - | Pprobe_is_enabled _ | Pobj_dup | Pobj_magic _ | Punbox_float - | Pbox_float _ | Punbox_int _ | Pbox_int _ | Parray_of_iarray - | Parray_to_iarray -> - assert false - in + let result_layout = L.primitive_result_layout prim in + (match result_layout with + | Pvalue _ | Punboxed_float | Punboxed_int _ | Punboxed_product _ -> () + | Ptop | Pbottom -> + Misc.fatal_errorf "Invalid result layout %a for primitive %a" + Printlambda.layout result_layout Printlambda.primitive prim); + (* CR mshinwell: find a way of making these lets non-user-visible *) cps acc env ccenv (L.Llet (Strict, result_layout, id, lam, L.Lvar id)) - k k_exn - | Pbytes_to_string | Pbytes_of_string | Pignore | Pgetglobal _ - | Psetglobal _ | Pgetpredef _ | Pmakeblock _ | Pmakefloatblock _ | Pfield _ - | Pfield_computed _ | Psetfield _ | Psetfield_computed _ | Pfloatfield _ - | Psetfloatfield _ | Pduprecord _ | Pccall _ | Praise _ | Psequand | Psequor - | Pnot | Pnegint | Paddint | Psubint | Pmulint | Pdivint _ | Pmodint _ - | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ - | Pcompare_ints | Pcompare_floats | Pcompare_bints _ | Poffsetint _ - | Poffsetref _ | Pintoffloat | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ - | Paddfloat _ | Psubfloat _ | Pmulfloat _ | Pdivfloat _ | Pfloatcomp _ - | Pstringlength | Pstringrefu | Pstringrefs | Pbyteslength | Pbytesrefu - | Pbytessetu | Pbytesrefs | Pbytessets | Pmakearray _ | Pduparray _ - | Parraylength _ | Parrayrefu _ | Parraysetu _ | Parrayrefs _ | Parraysets _ - | Pisint _ | Pisout | Pbintofint _ | Pintofbint _ | Pcvtbint _ | Pnegbint _ - | Paddbint _ | Psubbint _ | Pmulbint _ | Pdivbint _ | Pmodbint _ - | Pandbint _ | Porbint _ | Pxorbint _ | Plslbint _ | Plsrbint _ | Pasrbint _ - | Pbintcomp _ | Pbigarrayref _ | Pbigarrayset _ | Pbigarraydim _ - | Pstring_load_16 _ | Pstring_load_32 _ | Pstring_load_64 _ - | Pbytes_load_16 _ | Pbytes_load_32 _ | Pbytes_load_64 _ | Pbytes_set_16 _ - | Pbytes_set_32 _ | Pbytes_set_64 _ | Pbigstring_load_16 _ - | Pbigstring_load_32 _ | Pbigstring_load_64 _ | Pbigstring_set_16 _ - | Pbigstring_set_32 _ | Pbigstring_set_64 _ | Pctconst _ | Pbswap16 - | Pbbswap _ | Pint_as_pointer | Popaque _ | Pprobe_is_enabled _ | Pobj_dup - | Pobj_magic _ | Punbox_float | Pbox_float _ | Punbox_int _ | Pbox_int _ - | Parray_of_iarray | Parray_to_iarray -> ( - match - transform_primitive env (Ident.create_local "dummy") prim args loc - with - | Primitive (prim, args, loc) -> ( - let name = Printlambda.name_of_primitive prim in - let result_var = Ident.create_local name in - let exn_continuation : IR.exn_continuation option = - if primitive_can_raise prim - then - Some - { exn_handler = k_exn; - extra_args = extra_args_for_exn_continuation env k_exn - } - else None - in - let current_region = Env.current_region env in - let dbg = Debuginfo.from_location loc in - let arity = primitive_result_kind prim in - match Flambda_arity.must_be_one_param arity with - | None -> - Misc.fatal_errorf - "Expected the following Lprim to require exactly one\n\ - \ variable binding:@ %a" Printlambda.lambda lam - | Some kind -> - cps_non_tail_list acc env ccenv args - (fun acc env ccenv args _arity -> - let body acc ccenv = - apply_cps_cont ~dbg k acc env ccenv result_var (Singleton kind) - in - CC.close_let acc ccenv result_var Not_user_visible kind - (Prim - { prim; - args; - loc; - exn_continuation; - region = current_region - }) - ~body) - k_exn) - | Unboxed_binding _ -> assert false - | Transformed lam -> cps acc env ccenv lam k k_exn)) + k k_exn) | Lswitch (scrutinee, switch, loc, kind) -> maybe_insert_let_cont "switch_result" kind k acc env ccenv (fun acc env ccenv k -> diff --git a/ocaml/lambda/lambda.ml b/ocaml/lambda/lambda.ml index 692d5b8c873..bfcce603aac 100644 --- a/ocaml/lambda/lambda.ml +++ b/ocaml/lambda/lambda.ml @@ -1436,7 +1436,7 @@ let primitive_result_layout (p : primitive) = | Pmakeblock _ | Pmakefloatblock _ | Pmakearray _ | Pduprecord _ | Pduparray _ | Pbigarraydim _ | Pobj_dup -> layout_block | Pfield _ | Pfield_computed _ -> layout_field - | Punboxed_product_field _ -> Misc.fatal_error "Not supported" + | Punboxed_product_field (field, layouts) -> (Array.of_list layouts).(field) | Pmake_unboxed_product layouts -> layout_unboxed_product layouts | Pfloatfield _ | Pfloatofint _ | Pnegfloat _ | Pabsfloat _ | Paddfloat _ | Psubfloat _ | Pmulfloat _ | Pdivfloat _ From 05b2d2d245b05300a474cdcce57a8eb857b35ff9 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Thu, 11 May 2023 16:45:10 +0200 Subject: [PATCH 09/30] Further fixes for raise --- .../from_lambda/closure_conversion.ml | 56 +++++++++---------- .../from_lambda/closure_conversion.mli | 3 +- .../flambda2/from_lambda/lambda_to_flambda.ml | 28 +++++----- ocaml/lambda/lambda.ml | 8 ++- 4 files changed, 48 insertions(+), 47 deletions(-) diff --git a/middle_end/flambda2/from_lambda/closure_conversion.ml b/middle_end/flambda2/from_lambda/closure_conversion.ml index 43d19dae899..cbc0b16db26 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion.ml @@ -598,9 +598,32 @@ let close_exn_continuation acc env (exn_continuation : IR.exn_continuation) = Exn_continuation.create ~exn_handler:exn_continuation.exn_handler ~extra_args ) +let close_raise acc env ~raise_kind ~arg loc exn_continuation = + let acc, exn_cont = close_exn_continuation acc env exn_continuation in + let exn_handler = Exn_continuation.exn_handler exn_cont in + let acc, arg = find_simple acc env arg in + let args = + (* CR mshinwell: Share with [Lambda_to_flambda_primitives_helpers] *) + let extra_args = + List.map + (fun (simple, _kind) -> simple) + (Exn_continuation.extra_args exn_cont) + in + arg :: extra_args + in + let raise_kind = Some (Trap_action.Raise_kind.from_lambda raise_kind) in + let trap_action = Trap_action.Pop { exn_handler; raise_kind } in + let dbg = Debuginfo.from_location loc in + let acc, apply_cont = + Apply_cont_with_acc.create acc ~trap_action exn_handler ~args ~dbg + in + (* Since raising of an exception doesn't terminate, we don't call [k]. *) + Expr_with_acc.create_apply_cont acc apply_cont + let close_primitive acc env ~let_bound_var named (prim : Lambda.primitive) ~args loc (exn_continuation : IR.exn_continuation option) ~current_region (k : Acc.t -> Named.t option -> Expr_with_acc.t) : Expr_with_acc.t = + let orig_exn_continuation = exn_continuation in let acc, exn_continuation = match exn_continuation with | None -> acc, None @@ -608,6 +631,7 @@ let close_primitive acc env ~let_bound_var named (prim : Lambda.primitive) ~args let acc, cont = close_exn_continuation acc env exn_continuation in acc, Some cont in + let orig_args = args in let acc, args = find_simples acc env args in let dbg = Debuginfo.from_location loc in match prim, args with @@ -639,29 +663,14 @@ let close_primitive acc env ~let_bound_var named (prim : Lambda.primitive) ~args k acc (Some named) | Praise raise_kind, [_] -> let exn_continuation = - match exn_continuation with + match orig_exn_continuation with | None -> Misc.fatal_errorf "Praise is missing exception continuation: %a" IR.print_named named | Some exn_continuation -> exn_continuation in - let exn_handler = Exn_continuation.exn_handler exn_continuation in - let args = - (* CR mshinwell: Share with [Lambda_to_flambda_primitives_helpers] *) - let extra_args = - List.map - (fun (simple, _kind) -> simple) - (Exn_continuation.extra_args exn_continuation) - in - args @ extra_args - in - let raise_kind = Some (Trap_action.Raise_kind.from_lambda raise_kind) in - let trap_action = Trap_action.Pop { exn_handler; raise_kind } in - let acc, apply_cont = - Apply_cont_with_acc.create acc ~trap_action exn_handler ~args ~dbg - in - (* Since raising of an exception doesn't terminate, we don't call [k]. *) - Expr_with_acc.create_apply_cont acc apply_cont + close_raise acc env ~raise_kind ~arg:(List.hd orig_args) loc + exn_continuation | (Pmakeblock _ | Pmakefloatblock _ | Pmakearray _), [] -> (* Special case for liftable empty block or array *) let acc, sym = @@ -714,17 +723,6 @@ let close_primitive acc env ~let_bound_var named (prim : Lambda.primitive) ~args ~big_endian:(Env.big_endian env) ~register_const0 prim ~args dbg ~current_region k -let close_raise acc env ~raise_kind ~args loc exn_continuation ~current_region = - let prim : Lambda.primitive = Praise raise_kind in - let exn_continuation = Some exn_continuation in - let named : IR.named = - Prim { prim; args; loc; exn_continuation; region = current_region } - in - close_primitive acc env ~let_bound_var:(Variable.create "unused") named prim - ~args loc exn_continuation - ~current_region:(fst (Env.find_var env current_region)) - (fun _acc _named -> assert false (* see above *)) - let close_trap_action_opt trap_action = Option.map (fun (trap_action : IR.trap_action) : Trap_action.t -> diff --git a/middle_end/flambda2/from_lambda/closure_conversion.mli b/middle_end/flambda2/from_lambda/closure_conversion.mli index d2e619ca90a..bf087060817 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.mli +++ b/middle_end/flambda2/from_lambda/closure_conversion.mli @@ -74,10 +74,9 @@ val close_raise : Acc.t -> Env.t -> raise_kind:Lambda.raise_kind -> - args:IR.simple list -> + arg:IR.simple -> Lambda.scoped_location -> IR.exn_continuation -> - current_region:Ident.t -> Expr_with_acc.t type 'a close_program_metadata = diff --git a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml index 5e49290914b..cbf59c7aef6 100644 --- a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml +++ b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml @@ -1545,22 +1545,22 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation) | Dissected lam -> cps acc env ccenv lam k k_exn) | Lprim (prim, args, loc) -> ( match[@ocaml.warning "-fragile-match"] prim with - | Praise raise_kind -> - (match args with - | [_] -> () + | Praise raise_kind -> ( + match args with + | [_] -> + cps_non_tail_list acc env ccenv args + (fun acc _env ccenv args _arity -> + let exn_continuation : IR.exn_continuation = + { exn_handler = k_exn; + extra_args = extra_args_for_exn_continuation env k_exn + } + in + CC.close_raise acc ccenv ~raise_kind ~arg:(List.hd args) loc + exn_continuation) + k_exn | [] | _ :: _ -> Misc.fatal_errorf "Wrong number of arguments for Lraise: %a" - Printlambda.primitive prim); - cps_non_tail_list acc env ccenv args - (fun acc _env ccenv args _arity -> - let exn_continuation : IR.exn_continuation = - { exn_handler = k_exn; - extra_args = extra_args_for_exn_continuation env k_exn - } - in - CC.close_raise acc ccenv ~raise_kind ~args loc exn_continuation - ~current_region:(Env.current_region env)) - k_exn + Printlambda.primitive prim) | _ -> let id = Ident.create_local "prim" in let result_layout = L.primitive_result_layout prim in diff --git a/ocaml/lambda/lambda.ml b/ocaml/lambda/lambda.ml index bfcce603aac..f98247baccb 100644 --- a/ocaml/lambda/lambda.ml +++ b/ocaml/lambda/lambda.ml @@ -1424,6 +1424,7 @@ let structured_constant_layout = function | Const_float_array _ | Const_float_block _ -> Pvalue (Parrayval Pfloatarray) let primitive_result_layout (p : primitive) = + assert (Sys.backend_type = Sys.Native); match p with | Popaque layout | Pobj_magic layout -> layout | Pbytes_to_string | Pbytes_of_string -> layout_string @@ -1442,9 +1443,12 @@ let primitive_result_layout (p : primitive) = | Paddfloat _ | Psubfloat _ | Pmulfloat _ | Pdivfloat _ | Pbox_float _ -> layout_float | Punbox_float -> Punboxed_float - | Pccall _p -> - (* CR ncourant: use native_repr *) + | Pccall { prim_native_repr_res = _, Untagged_int; _} -> layout_int + | Pccall { prim_native_repr_res = _, Unboxed_float; _} -> layout_float + | Pccall { prim_native_repr_res = _, Same_as_ocaml_repr; _} -> layout_any_value + | Pccall { prim_native_repr_res = _, Unboxed_integer bi; _} -> + layout_boxedint bi | Praise _ -> layout_bottom | Psequor | Psequand | Pnot | Pnegint | Paddint | Psubint | Pmulint From b2afee7c7caf2df3429c99875db4d093ea990301 Mon Sep 17 00:00:00 2001 From: Vincent Laviron Date: Thu, 11 May 2023 14:30:19 +0200 Subject: [PATCH 10/30] Restrict the type of Flambda_arity.unarize_t --- middle_end/flambda2/from_lambda/closure_conversion.ml | 6 ++++-- middle_end/flambda2/kinds/flambda_arity.mli | 2 +- middle_end/flambda2/simplify_shared/inlining_helpers.mli | 2 +- middle_end/flambda2/terms/code_metadata.ml | 4 ++-- middle_end/flambda2/terms/code_metadata.mli | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/middle_end/flambda2/from_lambda/closure_conversion.ml b/middle_end/flambda2/from_lambda/closure_conversion.ml index cbc0b16db26..00ae56480a0 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion.ml @@ -1553,7 +1553,8 @@ let close_one_function acc ~code_id ~external_env ~by_function_slot decl Code.create code_id ~params_and_body ~free_names_of_params_and_body:(Acc.free_names acc) ~params_arity ~num_trailing_local_params:(Function_decl.num_trailing_local_params decl) - ~result_arity:return ~result_types:Unknown + ~result_arity:(Flambda_arity.unarize_t return) + ~result_types:Unknown ~contains_no_escaping_local_allocs: (Function_decl.contains_no_escaping_local_allocs decl) ~stub ~inline @@ -1682,7 +1683,8 @@ let close_functions acc external_env ~current_region function_declarations = Code_metadata.create code_id ~params_arity ~num_trailing_local_params: (Function_decl.num_trailing_local_params decl) - ~result_arity ~result_types:Unknown + ~result_arity:(Flambda_arity.unarize_t result_arity) + ~result_types:Unknown ~contains_no_escaping_local_allocs: (Function_decl.contains_no_escaping_local_allocs decl) ~stub:(Function_decl.stub decl) ~inline:Never_inline ~check diff --git a/middle_end/flambda2/kinds/flambda_arity.mli b/middle_end/flambda2/kinds/flambda_arity.mli index 18d1ec381df..8701656c81a 100644 --- a/middle_end/flambda2/kinds/flambda_arity.mli +++ b/middle_end/flambda2/kinds/flambda_arity.mli @@ -73,7 +73,7 @@ val unarize : _ t -> Flambda_kind.With_subkind.t list val unarize_per_parameter : _ t -> Flambda_kind.With_subkind.t list list (** Like [unarize] but returns a value of type [t]. *) -val unarize_t : _ t -> [> `Unarized] t +val unarize_t : _ t -> [`Unarized] t (** Given an arity and an identifier, produce a list of identifiers (with corresponding kinds) whose length matches [unarize t], with names derived diff --git a/middle_end/flambda2/simplify_shared/inlining_helpers.mli b/middle_end/flambda2/simplify_shared/inlining_helpers.mli index 8f97825168b..27ab89d8799 100644 --- a/middle_end/flambda2/simplify_shared/inlining_helpers.mli +++ b/middle_end/flambda2/simplify_shared/inlining_helpers.mli @@ -46,7 +46,7 @@ val wrap_inlined_body_for_exn_extra_args : extra_args:(Simple.t * Flambda_kind.With_subkind.t) list -> apply_exn_continuation:Exn_continuation.t -> apply_return_continuation:Flambda.Apply.Result_continuation.t -> - result_arity:[`Unarized | `Complex] Flambda_arity.t -> + result_arity:[`Unarized] Flambda_arity.t -> make_inlined_body: ('acc -> apply_exn_continuation:Continuation.t -> diff --git a/middle_end/flambda2/terms/code_metadata.ml b/middle_end/flambda2/terms/code_metadata.ml index 4a44b597e4e..929837ec33e 100644 --- a/middle_end/flambda2/terms/code_metadata.ml +++ b/middle_end/flambda2/terms/code_metadata.ml @@ -19,7 +19,7 @@ type t = newer_version_of : Code_id.t option; params_arity : [`Unarized | `Complex] Flambda_arity.t; num_trailing_local_params : int; - result_arity : [`Unarized | `Complex] Flambda_arity.t; + result_arity : [`Unarized] Flambda_arity.t; result_types : Result_types.t Or_unknown_or_bottom.t; contains_no_escaping_local_allocs : bool; stub : bool; @@ -126,7 +126,7 @@ type 'a create_type = newer_version_of:Code_id.t option -> params_arity:[`Unarized | `Complex] Flambda_arity.t -> num_trailing_local_params:int -> - result_arity:[`Unarized | `Complex] Flambda_arity.t -> + result_arity:[`Unarized] Flambda_arity.t -> result_types:Result_types.t Or_unknown_or_bottom.t -> contains_no_escaping_local_allocs:bool -> stub:bool -> diff --git a/middle_end/flambda2/terms/code_metadata.mli b/middle_end/flambda2/terms/code_metadata.mli index d3f5aceb9be..65dedac4403 100644 --- a/middle_end/flambda2/terms/code_metadata.mli +++ b/middle_end/flambda2/terms/code_metadata.mli @@ -38,7 +38,7 @@ module type Code_metadata_accessors_result_type = sig (* XXX rename to num_trailing_local_non_unarized_params *) val num_trailing_local_params : 'a t -> int - val result_arity : 'a t -> [`Unarized | `Complex] Flambda_arity.t + val result_arity : 'a t -> [`Unarized] Flambda_arity.t val result_types : 'a t -> Result_types.t Or_unknown_or_bottom.t @@ -85,7 +85,7 @@ type 'a create_type = newer_version_of:Code_id.t option -> params_arity:[`Unarized | `Complex] Flambda_arity.t -> num_trailing_local_params:int -> - result_arity:[`Unarized | `Complex] Flambda_arity.t -> + result_arity:[`Unarized] Flambda_arity.t -> result_types:Result_types.t Or_unknown_or_bottom.t -> contains_no_escaping_local_allocs:bool -> stub:bool -> From e7102f8d2cc96764461d103b6eef250f42d2a634 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Thu, 11 May 2023 14:46:46 +0200 Subject: [PATCH 11/30] Restrict a bit more Flambda_arity.t --- .../bound_identifiers/bound_parameters.mli | 2 +- .../from_lambda/closure_conversion.ml | 6 ++--- .../from_lambda/closure_conversion_aux.ml | 8 +++---- .../from_lambda/closure_conversion_aux.mli | 12 +++++----- .../flambda2/from_lambda/lambda_to_flambda.ml | 18 +++++++------- middle_end/flambda2/kinds/flambda_arity.ml | 15 ++++++++---- middle_end/flambda2/kinds/flambda_arity.mli | 24 ++++++++++--------- .../flambda2/parser/flambda_to_fexpr.ml | 22 ++++++++++------- .../simplify/env/continuation_uses.ml | 6 ++--- middle_end/flambda2/simplify/expr_builder.ml | 4 ++-- .../inlining/call_site_inlining_decision.ml | 2 +- .../inlining/call_site_inlining_decision.mli | 2 +- .../flambda2/simplify/simplify_apply_expr.ml | 24 +++++++++---------- .../flambda2/simplify/simplify_common.ml | 6 ++--- .../simplify/simplify_set_of_closures.ml | 4 ++-- .../simplify_shared/inlining_helpers.ml | 2 +- middle_end/flambda2/terms/apply_expr.ml | 4 ++-- middle_end/flambda2/terms/apply_expr.mli | 6 ++--- middle_end/flambda2/terms/code_metadata.ml | 4 ++-- middle_end/flambda2/terms/code_metadata.mli | 4 ++-- middle_end/flambda2/to_cmm/to_cmm_env.ml | 2 +- middle_end/flambda2/to_cmm/to_cmm_expr.ml | 2 +- middle_end/flambda2/to_cmm/to_cmm_shared.ml | 2 +- middle_end/flambda2/to_cmm/to_cmm_shared.mli | 2 +- middle_end/flambda2/types/flambda2_types.mli | 4 ++-- .../types/grammar/more_type_creators.ml | 3 ++- .../types/grammar/more_type_creators.mli | 4 ++-- 27 files changed, 104 insertions(+), 90 deletions(-) diff --git a/middle_end/flambda2/bound_identifiers/bound_parameters.mli b/middle_end/flambda2/bound_identifiers/bound_parameters.mli index 418078cf20d..9a9607f1637 100644 --- a/middle_end/flambda2/bound_identifiers/bound_parameters.mli +++ b/middle_end/flambda2/bound_identifiers/bound_parameters.mli @@ -30,7 +30,7 @@ val is_empty : t -> bool val same_number : t -> t -> bool -val arity : t -> [> `Unarized] Flambda_arity.t +val arity : t -> [>] Flambda_arity.t val check_no_duplicates : t -> unit diff --git a/middle_end/flambda2/from_lambda/closure_conversion.ml b/middle_end/flambda2/from_lambda/closure_conversion.ml index 00ae56480a0..0e9eb0942a5 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion.ml @@ -2188,13 +2188,13 @@ type call_args_split = | Exact of IR.simple list | Partial_app of { provided : IR.simple list; - missing_arity : [`Unarized | `Complex] Flambda_arity.t + missing_arity : [`Complex] Flambda_arity.t } | Over_app of { full : IR.simple list; - provided_arity : [`Unarized | `Complex] Flambda_arity.t; + provided_arity : [`Complex] Flambda_arity.t; remaining : IR.simple list; - remaining_arity : [`Unarized | `Complex] Flambda_arity.t + remaining_arity : [`Complex] Flambda_arity.t } let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = diff --git a/middle_end/flambda2/from_lambda/closure_conversion_aux.ml b/middle_end/flambda2/from_lambda/closure_conversion_aux.ml index c8a678dd818..bb7d7683639 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion_aux.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion_aux.ml @@ -64,8 +64,8 @@ module IR = struct probe : Lambda.probe; mode : Lambda.alloc_mode; region : Ident.t; - args_arity : [`Unarized | `Complex] Flambda_arity.t; - return_arity : [`Unarized | `Complex] Flambda_arity.t + args_arity : [`Complex] Flambda_arity.t; + return_arity : [`Complex] Flambda_arity.t } type switch = @@ -676,8 +676,8 @@ module Function_decls = struct kind : Lambda.function_kind; params : (Ident.t * Flambda_kind.With_subkind.t) list; removed_params : Ident.Set.t; - params_arity : [`Unarized | `Complex] Flambda_arity.t; - return : [`Unarized | `Complex] Flambda_arity.t; + params_arity : [`Complex] Flambda_arity.t; + return : [`Complex] Flambda_arity.t; return_continuation : Continuation.t; exn_continuation : IR.exn_continuation; my_region : Ident.t; diff --git a/middle_end/flambda2/from_lambda/closure_conversion_aux.mli b/middle_end/flambda2/from_lambda/closure_conversion_aux.mli index cd8e16232fa..bd9e3c06efa 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion_aux.mli +++ b/middle_end/flambda2/from_lambda/closure_conversion_aux.mli @@ -68,8 +68,8 @@ module IR : sig probe : Lambda.probe; mode : Lambda.alloc_mode; region : Ident.t; - args_arity : [`Unarized | `Complex] Flambda_arity.t; - return_arity : [`Unarized | `Complex] Flambda_arity.t + args_arity : [`Complex] Flambda_arity.t; + return_arity : [`Complex] Flambda_arity.t } type switch = @@ -301,9 +301,9 @@ module Function_decls : sig function_slot:Function_slot.t -> kind:Lambda.function_kind -> params:(Ident.t * Flambda_kind.With_subkind.t) list -> - params_arity:[`Unarized | `Complex] Flambda_arity.t -> + params_arity:[`Complex] Flambda_arity.t -> removed_params:Ident.Set.t -> - return:[`Unarized | `Complex] Flambda_arity.t -> + return:[`Complex] Flambda_arity.t -> return_continuation:Continuation.t -> exn_continuation:IR.exn_continuation -> my_region:Ident.t -> @@ -325,9 +325,9 @@ module Function_decls : sig val params : t -> (Ident.t * Flambda_kind.With_subkind.t) list - val params_arity : t -> [`Unarized | `Complex] Flambda_arity.t + val params_arity : t -> [`Complex] Flambda_arity.t - val return : t -> [`Unarized | `Complex] Flambda_arity.t + val return : t -> [`Complex] Flambda_arity.t val return_continuation : t -> Continuation.t diff --git a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml index cbf59c7aef6..89f3453eed2 100644 --- a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml +++ b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml @@ -56,14 +56,14 @@ module Env : sig t -> unboxed_product:Ident.t -> before_unarization: - [`Unarized | `Complex] Flambda_arity.Component_for_creation.t -> + [`Complex] Flambda_arity.Component_for_creation.t -> fields:(Ident.t * Flambda_kind.With_subkind.t) list -> t val get_unboxed_product_fields : t -> Ident.t -> - ([`Unarized | `Complex] Flambda_arity.Component_for_creation.t + ([`Complex] Flambda_arity.Component_for_creation.t * Ident.t list) option @@ -207,7 +207,7 @@ end = struct (Ident.t * Flambda_kind.With_subkind.t) Ident.Map.t; mutables_needed_by_continuations : Ident.Set.t Continuation.Map.t; unboxed_product_components_in_scope : - ([`Unarized | `Complex] Flambda_arity.Component_for_creation.t + ([`Complex] Flambda_arity.Component_for_creation.t * (Ident.t * Flambda_kind.With_subkind.t) array) Ident.Map.t; unboxed_product_components_needed_by_continuations : @@ -1259,7 +1259,7 @@ type non_tail_continuation = Env.t -> CCenv.t -> IR.simple list -> - [`Unarized | `Complex] Flambda_arity.Component_for_creation.t -> + [`Complex] Flambda_arity.Component_for_creation.t -> Expr_with_acc.t type non_tail_list_continuation = @@ -1267,7 +1267,7 @@ type non_tail_list_continuation = Env.t -> CCenv.t -> IR.simple list -> - [`Unarized | `Complex] Flambda_arity.Component_for_creation.t list -> + [`Complex] Flambda_arity.Component_for_creation.t list -> Expr_with_acc.t type cps_continuation = @@ -1276,14 +1276,14 @@ type cps_continuation = let apply_cps_cont_simple k ?(dbg = Debuginfo.none) acc env ccenv simples (arity_component : - [`Unarized | `Complex] Flambda_arity.Component_for_creation.t) = + [`Complex] Flambda_arity.Component_for_creation.t) = match k with | Tail k -> apply_cont_with_extra_args acc env ccenv ~dbg k None simples | Non_tail k -> k acc env ccenv simples arity_component let apply_cps_cont k ?dbg acc env ccenv id (arity_component : - [`Unarized | `Complex] Flambda_arity.Component_for_creation.t) = + [`Complex] Flambda_arity.Component_for_creation.t) = apply_cps_cont_simple k ?dbg acc env ccenv [IR.Var id] arity_component let maybe_insert_let_cont result_var_name layout k acc env ccenv body = @@ -1853,7 +1853,7 @@ and cps_non_tail_var : Env.t -> CCenv.t -> Ident.t -> - [`Unarized | `Complex] Flambda_arity.Component_for_creation.t -> + [`Complex] Flambda_arity.Component_for_creation.t -> Expr_with_acc.t) -> Continuation.t -> Expr_with_acc.t = @@ -1918,7 +1918,7 @@ and cps_non_tail_list : cps_non_tail_list_core acc env ccenv lams (fun acc env ccenv ids (arity : - [`Unarized | `Complex] Flambda_arity.Component_for_creation.t list) -> + [`Complex] Flambda_arity.Component_for_creation.t list) -> k acc env ccenv (List.rev ids) (List.rev arity)) k_exn diff --git a/middle_end/flambda2/kinds/flambda_arity.ml b/middle_end/flambda2/kinds/flambda_arity.ml index 0b2c8c8a3d8..9810ac6171e 100644 --- a/middle_end/flambda2/kinds/flambda_arity.ml +++ b/middle_end/flambda2/kinds/flambda_arity.ml @@ -16,8 +16,8 @@ module Component = struct type _ t = - | Singleton : Flambda_kind.With_subkind.t -> [> `Unarized] t - | Unboxed_product : _ t list -> [> `Complex] t + | Singleton : Flambda_kind.With_subkind.t -> [> ] t + | Unboxed_product : _ t list -> [`Complex] t let rec equal_ignoring_subkinds : type uc1 uc2. uc1 t -> uc2 t -> bool = fun t1 t2 -> @@ -58,14 +58,19 @@ module Component = struct | Singleton kind -> [kind] | Unboxed_product [] -> [] | Unboxed_product ts -> List.concat_map unarize ts + + let component : [`Unarized] t -> Flambda_kind.With_subkind.t = + fun t -> + match t with + | Singleton kind -> kind end type 'uc t = 'uc Component.t list module Component_for_creation = struct type 'uc t = 'uc Component.t = - | Singleton : Flambda_kind.With_subkind.t -> [> `Unarized] t - | Unboxed_product : _ t list -> [> `Complex] t + | Singleton : Flambda_kind.With_subkind.t -> [> ] t + | Unboxed_product : _ t list -> [`Complex] t let rec from_lambda (layout : Lambda.layout) = match layout with @@ -110,6 +115,8 @@ let is_one_param_of_kind_value : type uc. uc t -> bool = let unarize t = t |> List.map Component.unarize |> List.concat +let unarized_components (t : [`Unarized] t) = List.map Component.component t + let unarize_per_parameter t = t |> List.map Component.unarize let unarize_t t = t |> unarize |> create_singletons diff --git a/middle_end/flambda2/kinds/flambda_arity.mli b/middle_end/flambda2/kinds/flambda_arity.mli index 8701656c81a..df939319477 100644 --- a/middle_end/flambda2/kinds/flambda_arity.mli +++ b/middle_end/flambda2/kinds/flambda_arity.mli @@ -32,21 +32,21 @@ type _ t module Component_for_creation : sig type _ t = - | Singleton : Flambda_kind.With_subkind.t -> [> `Unarized] t + | Singleton : Flambda_kind.With_subkind.t -> [> ] t (* The nullary unboxed product is called "void". It is important to propagate information about void layouts, even though the corresponding variables have no runtime representation, as they interact with currying. *) - | Unboxed_product : _ t list -> [> `Complex] t + | Unboxed_product : _ t list -> [`Complex] t - val from_lambda : Lambda.layout -> [`Unarized | `Complex] t + val from_lambda : Lambda.layout -> [`Complex] t end (** One component per function or continuation parameter, for example. Each component may in turn have an arity describing an unboxed product. *) val create : 'uc Component_for_creation.t list -> 'uc t -val create_singletons : Flambda_kind.With_subkind.t list -> [> `Unarized] t +val create_singletons : Flambda_kind.With_subkind.t list -> [> ] t (** "No parameters". (Not e.g. "one parameter of type void".) *) val nullary : [> `Unarized] t @@ -55,11 +55,11 @@ val num_params : _ t -> int val print : Format.formatter -> _ t -> unit -val equal_ignoring_subkinds : _ t -> _ t -> bool +val equal_ignoring_subkinds : 'a t -> 'a t -> bool (* It's usually a mistake to use this function, but it's needed for [Compare]. *) -val equal_exact : _ t -> _ t -> bool +val equal_exact : 'a t -> 'a t -> bool val is_one_param_of_kind_value : _ t -> bool @@ -67,13 +67,15 @@ val must_be_one_param : _ t -> Flambda_kind.With_subkind.t option (** Converts, in a left-to-right depth-first order, an arity into a flattened list of kinds for all parameters. *) -val unarize : _ t -> Flambda_kind.With_subkind.t list +val unarize : [`Complex] t -> Flambda_kind.With_subkind.t list + +val unarized_components : [`Unarized] t -> Flambda_kind.With_subkind.t list (** Like [unarize] but returns one list per parameter. *) -val unarize_per_parameter : _ t -> Flambda_kind.With_subkind.t list list +val unarize_per_parameter : [`Complex] t -> Flambda_kind.With_subkind.t list list (** Like [unarize] but returns a value of type [t]. *) -val unarize_t : _ t -> [`Unarized] t +val unarize_t : [`Complex] t -> [`Unarized] t (** Given an arity and an identifier, produce a list of identifiers (with corresponding kinds) whose length matches [unarize t], with names derived @@ -86,8 +88,8 @@ val cardinal_unarized : _ t -> int (** Take a list of Lambda layouts, one per parameter, and form the corresponding arity. *) -val from_lambda_list : Lambda.layout list -> [`Unarized | `Complex] t +val from_lambda_list : Lambda.layout list -> [`Complex] t (** Remove the first portion of an arity to correspond to a partial application. *) -val partially_apply : 'uc t -> num_non_unarized_params_provided:int -> 'uc t +val partially_apply : [`Complex] t -> num_non_unarized_params_provided:int -> [`Complex] t diff --git a/middle_end/flambda2/parser/flambda_to_fexpr.ml b/middle_end/flambda2/parser/flambda_to_fexpr.ml index 71bf5fa83c5..03104a1f8a3 100644 --- a/middle_end/flambda2/parser/flambda_to_fexpr.ml +++ b/middle_end/flambda2/parser/flambda_to_fexpr.ml @@ -452,16 +452,22 @@ let kind_with_subkind_opt (k : Flambda_kind.With_subkind.t) : Fexpr.kind_with_subkind option = if is_default_kind_with_subkind k then None else Some (k |> kind_with_subkind) -let is_default_arity (a : _ Flambda_arity.t) = - match Flambda_arity.unarize a with +let is_default_arity (a : [`Unarized] Flambda_arity.t) = + match Flambda_arity.unarized_components a with | [k] -> is_default_kind_with_subkind k | _ -> false -let arity (a : _ Flambda_arity.t) : Fexpr.arity = +let complex_arity (a : [`Complex] Flambda_arity.t) : Fexpr.arity = (* CR mshinwell: add unboxed arities to Fexpr *) - Flambda_arity.unarize a |> List.map kind_with_subkind + Flambda_arity.unarize a + |> List.map kind_with_subkind -let arity_opt (a : _ Flambda_arity.t) : Fexpr.arity option = +let arity (a : [`Unarized] Flambda_arity.t) : Fexpr.arity = + (* CR mshinwell: add unboxed arities to Fexpr *) + Flambda_arity.unarized_components a + |> List.map kind_with_subkind + +let arity_opt (a : [`Unarized] Flambda_arity.t) : Fexpr.arity option = if is_default_arity a then None else Some (arity a) let kinded_parameter env (kp : Bound_parameter.t) : @@ -800,7 +806,7 @@ and static_let_expr env bound_static defining_expr body : Fexpr.expr = let newer_version_of = Option.map (Env.find_code_id_exn env) (Code.newer_version_of code) in - let param_arity = Some (arity (Code.params_arity code)) in + let param_arity = Some (complex_arity (Code.params_arity code)) in let ret_arity = Code.result_arity code |> arity_opt in let recursive = recursive_flag (Code.recursive code) in let inline = @@ -1002,7 +1008,7 @@ and apply_expr env (app : Apply_expr.t) : Fexpr.expr = let arities : Fexpr.function_arities option = match Apply_expr.call_kind app with | Function { function_call = Indirect_known_arity; alloc_mode = _ } -> - let params_arity = Some (arity param_arity) in + let params_arity = Some (complex_arity param_arity) in let ret_arity = arity return_arity in Some { params_arity; ret_arity } | Function { function_call = Direct _; alloc_mode = _ } -> @@ -1016,7 +1022,7 @@ and apply_expr env (app : Apply_expr.t) : Fexpr.expr = let ret_arity = arity return_arity in Some { params_arity; ret_arity } | C_call _ -> - let params_arity = Some (arity param_arity) in + let params_arity = Some (complex_arity param_arity) in let ret_arity = arity return_arity in Some { params_arity; ret_arity } | Function { function_call = Indirect_unknown_arity; alloc_mode = _ } diff --git a/middle_end/flambda2/simplify/env/continuation_uses.ml b/middle_end/flambda2/simplify/env/continuation_uses.ml index e6b6bb0ecd1..42cb5321859 100644 --- a/middle_end/flambda2/simplify/env/continuation_uses.ml +++ b/middle_end/flambda2/simplify/env/continuation_uses.ml @@ -95,7 +95,7 @@ let add_uses_to_arg_maps arg_maps uses = let empty_arg_maps arity : arg_types_by_use_id = List.map (fun _ -> Apply_cont_rewrite_id.Map.empty) - (Flambda_arity.unarize arity) + (Flambda_arity.unarized_components arity) let get_arg_types_by_use_id t = add_uses_to_arg_maps (empty_arg_maps t.arity) t.uses @@ -108,10 +108,10 @@ let get_arg_types_by_use_id_for_invariant_params arity l = (fun arg_maps t -> if not (Misc.Stdlib.List.is_prefix ~equal:Flambda_kind.equal - (Flambda_arity.unarize arity + (Flambda_arity.unarized_components arity |> List.map Flambda_kind.With_subkind.kind) ~of_: - (Flambda_arity.unarize t.arity + (Flambda_arity.unarized_components t.arity |> List.map Flambda_kind.With_subkind.kind)) then Misc.fatal_errorf diff --git a/middle_end/flambda2/simplify/expr_builder.ml b/middle_end/flambda2/simplify/expr_builder.ml index 18a7d054906..d593cc3eae7 100644 --- a/middle_end/flambda2/simplify/expr_builder.ml +++ b/middle_end/flambda2/simplify/expr_builder.ml @@ -744,9 +744,9 @@ let rewrite_fixed_arity_continuation0 uacc cont_or_apply_cont ~use_id arity : let params = List.map (fun _kind -> Variable.create "param") - (Flambda_arity.unarize arity) + (Flambda_arity.unarized_components arity) in - let params = List.map2 BP.create params (Flambda_arity.unarize arity) in + let params = List.map2 BP.create params (Flambda_arity.unarized_components arity) in let args = List.map BP.simple params in let params = Bound_parameters.create params in let apply_cont = Apply_cont.create cont ~args ~dbg:Debuginfo.none in diff --git a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml index 85b46ce8172..dc74eb18edb 100644 --- a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml +++ b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.ml @@ -116,7 +116,7 @@ let speculative_inlining dacc ~apply ~function_type ~simplify_expr ~return_arity | Never_returns -> uenv | Return return_continuation -> UE.add_function_return_or_exn_continuation uenv return_continuation - (Flambda_arity.unarize_t return_arity) + return_arity in let uacc = UA.create ~flow_result ~compute_slot_offsets:false uenv dacc diff --git a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli index 138118521a9..d593eb39ab2 100644 --- a/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli +++ b/middle_end/flambda2/simplify/inlining/call_site_inlining_decision.mli @@ -21,7 +21,7 @@ val make_decision : simplify_expr:Expr.t Simplify_common.expr_simplifier -> function_type:Flambda2_types.Function_type.t -> apply:Apply.t -> - return_arity:_ Flambda_arity.t -> + return_arity:[`Unarized] Flambda_arity.t -> Call_site_inlining_decision_type.t val get_rec_info : diff --git a/middle_end/flambda2/simplify/simplify_apply_expr.ml b/middle_end/flambda2/simplify/simplify_apply_expr.ml index 35492c5ee3c..80e0fc0b68d 100644 --- a/middle_end/flambda2/simplify/simplify_apply_expr.ml +++ b/middle_end/flambda2/simplify/simplify_apply_expr.ml @@ -165,9 +165,7 @@ let rebuild_non_inlined_direct_full_application apply ~use_id ~exn_cont_use_id in uacc, RE.create_apply (UA.are_rebuilding_terms uacc) apply | Some use_id -> - EB.rewrite_fixed_arity_apply uacc ~use_id - (Flambda_arity.unarize_t result_arity) - apply + EB.rewrite_fixed_arity_apply uacc ~use_id result_arity apply in after_rebuild expr uacc @@ -273,7 +271,7 @@ let simplify_direct_full_application ~simplify_expr dacc apply function_type arg)) denv params args in - let result_arity = Flambda_arity.unarize result_arity in + let result_arity = Flambda_arity.unarized_components result_arity in let denv = List.fold_left2 (fun denv kind result -> @@ -584,7 +582,7 @@ let simplify_direct_partial_application ~simplify_expr dacc apply ~free_names_of_params_and_body:free_names ~newer_version_of:None ~params_arity:(Bound_parameters.arity remaining_params) ~num_trailing_local_params - ~result_arity:(Flambda_arity.unarize_t result_arity) + ~result_arity:result_arity ~result_types:Unknown ~contains_no_escaping_local_allocs ~stub:true ~inline:Default_inline ~poll_attribute:Default ~check:Check_attribute.Default_check ~is_a_functor:false ~recursive @@ -757,7 +755,7 @@ let simplify_direct_function_call ~simplify_expr dacc apply the function being overapplied returns kind Value. *) if not (Flambda_arity.equal_ignoring_subkinds - (Flambda_arity.unarize_t result_arity) + result_arity result_arity_of_application) then Misc.fatal_errorf @@ -794,7 +792,7 @@ let simplify_direct_function_call ~simplify_expr dacc apply simplify_direct_partial_application ~simplify_expr dacc apply ~callee's_code_id ~callee's_code_metadata ~callee's_function_slot ~param_arity:params_arity ~args_arity - ~result_arity:(Flambda_arity.unarize_t result_arity) + ~result_arity:result_arity ~recursive ~down_to_up ~coming_from_indirect ~closure_alloc_mode_from_type ~current_region ~num_trailing_local_non_unarized_params: @@ -818,7 +816,7 @@ let rebuild_function_call_where_callee's_type_unavailable apply call_kind in let uacc, expr = EB.rewrite_fixed_arity_apply uacc ~use_id - (Flambda_arity.unarize_t (Apply.return_arity apply)) + (Apply.return_arity apply) apply in after_rebuild expr uacc @@ -996,7 +994,7 @@ let rebuild_method_call apply ~use_id ~exn_cont_use_id uacc ~after_rebuild = in let uacc, expr = EB.rewrite_fixed_arity_apply uacc ~use_id - (Flambda_arity.unarize_t (Apply.return_arity apply)) + (Apply.return_arity apply) apply in after_rebuild expr uacc @@ -1020,7 +1018,8 @@ let simplify_method_call dacc apply ~callee_ty ~kind:_ ~obj ~arg_types let args_arity = Apply.args_arity apply in let args_arity_from_types = T.arity_of_list arg_types in if not - (Flambda_arity.equal_ignoring_subkinds args_arity_from_types args_arity) + (Flambda_arity.equal_ignoring_subkinds args_arity_from_types + (Flambda_arity.unarize_t args_arity)) then Misc.fatal_errorf "Arity %a of [Apply] arguments doesn't match parameter arity %a of \ @@ -1058,7 +1057,7 @@ let rebuild_c_call apply ~use_id ~exn_cont_use_id ~return_arity uacc match use_id with | Some use_id -> EB.rewrite_fixed_arity_apply uacc ~use_id - (Flambda_arity.unarize_t return_arity) + return_arity apply | None -> let uacc = @@ -1081,7 +1080,8 @@ let simplify_c_call ~simplify_expr dacc apply ~callee_ty ~arg_types ~down_to_up callee_kind T.print callee_ty; let args_arity_from_types = T.arity_of_list arg_types in if not - (Flambda_arity.equal_ignoring_subkinds args_arity_from_types args_arity) + (Flambda_arity.equal_ignoring_subkinds args_arity_from_types + (Flambda_arity.unarize_t args_arity)) then Misc.fatal_errorf "Arity %a of [Apply] arguments doesn't match parameter arity %a of C \ diff --git a/middle_end/flambda2/simplify/simplify_common.ml b/middle_end/flambda2/simplify/simplify_common.ml index d1962cffe94..f7648580eeb 100644 --- a/middle_end/flambda2/simplify/simplify_common.ml +++ b/middle_end/flambda2/simplify/simplify_common.ml @@ -180,7 +180,7 @@ let split_direct_over_application apply List.mapi (fun i kind -> BP.create (Variable.create ("result" ^ string_of_int i)) kind) - (Flambda_arity.unarize (Apply.return_arity apply)) + (Flambda_arity.unarized_components (Apply.return_arity apply)) in let call_return_continuation, call_return_continuation_free_names = match Apply.continuation apply with @@ -241,9 +241,7 @@ let split_direct_over_application apply ~continuation:(Return after_full_application) (Apply.exn_continuation apply) ~args:first_args ~args_arity:callee's_params_arity - ~return_arity: - (Flambda_arity.unarize_t - (Code_metadata.result_arity callee's_code_metadata)) + ~return_arity:(Code_metadata.result_arity callee's_code_metadata) ~call_kind:(Call_kind.direct_function_call callee's_code_id alloc_mode) (Apply.dbg apply) ~inlined:(Apply.inlined apply) ~inlining_state:(Apply.inlining_state apply) diff --git a/middle_end/flambda2/simplify/simplify_set_of_closures.ml b/middle_end/flambda2/simplify/simplify_set_of_closures.ml index 6b9bc705102..1871a9134ed 100644 --- a/middle_end/flambda2/simplify/simplify_set_of_closures.ml +++ b/middle_end/flambda2/simplify/simplify_set_of_closures.ml @@ -176,7 +176,7 @@ let simplify_function_body context ~outer_dacc function_slot_opt match C.simplify_function_body context dacc body ~return_continuation ~exn_continuation - ~return_arity:(Code.result_arity code |> Flambda_arity.unarize_t) + ~return_arity:(Code.result_arity code) ~implicit_params: (Bound_parameters.create [ Bound_parameter.create my_closure @@ -347,7 +347,7 @@ let simplify_function0 context ~outer_dacc function_slot_opt code_id code BP.create (Variable.create ("result" ^ string_of_int i)) kind_with_subkind) - (Flambda_arity.unarize result_arity) + (Flambda_arity.unarized_components result_arity) |> Bound_parameters.create in let { params; diff --git a/middle_end/flambda2/simplify_shared/inlining_helpers.ml b/middle_end/flambda2/simplify_shared/inlining_helpers.ml index 0f31c9168c7..386bd6843c3 100644 --- a/middle_end/flambda2/simplify_shared/inlining_helpers.ml +++ b/middle_end/flambda2/simplify_shared/inlining_helpers.ml @@ -72,7 +72,7 @@ let wrap_inlined_body_for_exn_extra_args acc ~extra_args ~apply_exn_continuation let kinded_params = List.map (fun k -> Bound_parameter.create (Variable.create "wrapper_return") k) - (Flambda_arity.unarize result_arity) + (Flambda_arity.unarized_components result_arity) in let trap_action = Trap_action.Pop { exn_handler = wrapper; raise_kind = None } diff --git a/middle_end/flambda2/terms/apply_expr.ml b/middle_end/flambda2/terms/apply_expr.ml index 2eadecc64c5..dd4cb428de1 100644 --- a/middle_end/flambda2/terms/apply_expr.ml +++ b/middle_end/flambda2/terms/apply_expr.ml @@ -73,7 +73,7 @@ type t = continuation : Result_continuation.t; exn_continuation : Exn_continuation.t; args : Simple.t list; - args_arity : [`Unarized | `Complex] Flambda_arity.t; + args_arity : [`Complex] Flambda_arity.t; return_arity : [`Unarized] Flambda_arity.t; call_kind : Call_kind.t; dbg : Debuginfo.t; @@ -158,7 +158,7 @@ let invariant "For [C_call] applications the callee must be directly specified as a \ [Symbol]:@ %a" print t; - match Flambda_arity.unarize return_arity with + match Flambda_arity.unarized_components return_arity with | [] | [_] -> () | _ :: _ :: _ -> Misc.fatal_errorf "Illegal return arity for C call:@ %a" diff --git a/middle_end/flambda2/terms/apply_expr.mli b/middle_end/flambda2/terms/apply_expr.mli index 0eda9561c42..3159218646a 100644 --- a/middle_end/flambda2/terms/apply_expr.mli +++ b/middle_end/flambda2/terms/apply_expr.mli @@ -51,7 +51,7 @@ val create : continuation:Result_continuation.t -> Exn_continuation.t -> args:Simple.t list -> - args_arity:[`Unarized | `Complex] Flambda_arity.t -> + args_arity:[`Complex] Flambda_arity.t -> return_arity:[`Unarized] Flambda_arity.t -> call_kind:Call_kind.t -> Debuginfo.t -> @@ -77,7 +77,7 @@ val callee : t -> Simple.t val args : t -> Simple.t list (** The arity of the arguments being applied. *) -val args_arity : t -> [`Unarized | `Complex] Flambda_arity.t +val args_arity : t -> [`Complex] Flambda_arity.t (** The arity of the result(s) of the application. *) val return_arity : t -> [`Unarized] Flambda_arity.t @@ -111,7 +111,7 @@ val with_exn_continuation : t -> Exn_continuation.t -> t (** Change the arguments of an application *) val with_args : - t -> Simple.t list -> args_arity:[`Unarized | `Complex] Flambda_arity.t -> t + t -> Simple.t list -> args_arity:[`Complex] Flambda_arity.t -> t (** Change the call kind of an application. *) val with_call_kind : t -> Call_kind.t -> t diff --git a/middle_end/flambda2/terms/code_metadata.ml b/middle_end/flambda2/terms/code_metadata.ml index 929837ec33e..0bbe47ef5d4 100644 --- a/middle_end/flambda2/terms/code_metadata.ml +++ b/middle_end/flambda2/terms/code_metadata.ml @@ -17,7 +17,7 @@ type t = { code_id : Code_id.t; newer_version_of : Code_id.t option; - params_arity : [`Unarized | `Complex] Flambda_arity.t; + params_arity : [`Complex] Flambda_arity.t; num_trailing_local_params : int; result_arity : [`Unarized] Flambda_arity.t; result_types : Result_types.t Or_unknown_or_bottom.t; @@ -124,7 +124,7 @@ include Code_metadata_accessors [@inlined hint] (Metadata_view) type 'a create_type = Code_id.t -> newer_version_of:Code_id.t option -> - params_arity:[`Unarized | `Complex] Flambda_arity.t -> + params_arity:[`Complex] Flambda_arity.t -> num_trailing_local_params:int -> result_arity:[`Unarized] Flambda_arity.t -> result_types:Result_types.t Or_unknown_or_bottom.t -> diff --git a/middle_end/flambda2/terms/code_metadata.mli b/middle_end/flambda2/terms/code_metadata.mli index 65dedac4403..67b88fd71c4 100644 --- a/middle_end/flambda2/terms/code_metadata.mli +++ b/middle_end/flambda2/terms/code_metadata.mli @@ -31,7 +31,7 @@ module type Code_metadata_accessors_result_type = sig val newer_version_of : 'a t -> Code_id.t option - val params_arity : 'a t -> [`Unarized | `Complex] Flambda_arity.t + val params_arity : 'a t -> [`Complex] Flambda_arity.t val num_leading_heap_params : 'a t -> int @@ -83,7 +83,7 @@ include Code_metadata_accessors_result_type with type 'a t := t type 'a create_type = Code_id.t -> newer_version_of:Code_id.t option -> - params_arity:[`Unarized | `Complex] Flambda_arity.t -> + params_arity:[`Complex] Flambda_arity.t -> num_trailing_local_params:int -> result_arity:[`Unarized] Flambda_arity.t -> result_types:Result_types.t Or_unknown_or_bottom.t -> diff --git a/middle_end/flambda2/to_cmm/to_cmm_env.ml b/middle_end/flambda2/to_cmm/to_cmm_env.ml index 46b694da2e1..c0fc3795ecf 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_env.ml +++ b/middle_end/flambda2/to_cmm/to_cmm_env.ml @@ -360,7 +360,7 @@ let add_exn_handler env k arity = let env = { env with exn_handlers = Continuation.Set.add k env.exn_handlers } in - match Flambda_arity.unarize arity with + match Flambda_arity.unarized_components arity with | [] -> Misc.fatal_error "Exception handlers must have at least one parameter" | [_] -> env, [] | _ :: extra_args -> diff --git a/middle_end/flambda2/to_cmm/to_cmm_expr.ml b/middle_end/flambda2/to_cmm/to_cmm_expr.ml index 388d13837f7..9eeca713a88 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_expr.ml +++ b/middle_end/flambda2/to_cmm/to_cmm_expr.ml @@ -182,7 +182,7 @@ let translate_apply0 ~dbg_with_inlined:dbg env res apply = in let returns = Apply.returns apply in let wrap = - match Flambda_arity.unarize return_arity with + match Flambda_arity.unarized_components return_arity with (* Returned int32 values need to be sign_extended because it's not clear whether C code that returns an int32 returns one that is sign extended or not. There is no need to wrap other return arities. Note that diff --git a/middle_end/flambda2/to_cmm/to_cmm_shared.ml b/middle_end/flambda2/to_cmm/to_cmm_shared.ml index 707d5e414dc..36d4ea51cbe 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_shared.ml +++ b/middle_end/flambda2/to_cmm/to_cmm_shared.ml @@ -250,7 +250,7 @@ let check_arity arity args = Flambda_arity.cardinal_unarized arity = List.length args let extended_machtype_of_return_arity arity = - match Flambda_arity.unarize arity with + match Flambda_arity.unarized_components arity with | [] -> (* Functions that never return have arity 0. In that case, we use the most restrictive machtype to ensure that the return value of the function is diff --git a/middle_end/flambda2/to_cmm/to_cmm_shared.mli b/middle_end/flambda2/to_cmm/to_cmm_shared.mli index ddfd3cfe6b4..ca901edff96 100644 --- a/middle_end/flambda2/to_cmm/to_cmm_shared.mli +++ b/middle_end/flambda2/to_cmm/to_cmm_shared.mli @@ -101,4 +101,4 @@ val make_update : val check_arity : _ Flambda_arity.t -> _ list -> bool val extended_machtype_of_return_arity : - _ Flambda_arity.t -> Cmm_helpers.Extended_machtype.t + [`Unarized] Flambda_arity.t -> Cmm_helpers.Extended_machtype.t diff --git a/middle_end/flambda2/types/flambda2_types.mli b/middle_end/flambda2/types/flambda2_types.mli index 19fcd258b5a..5d4e056ac12 100644 --- a/middle_end/flambda2/types/flambda2_types.mli +++ b/middle_end/flambda2/types/flambda2_types.mli @@ -515,10 +515,10 @@ val kind : t -> Flambda_kind.t val get_alias_exn : t -> Simple.t (** For each of the kinds in an arity, create an "unknown" type. *) -val unknown_types_from_arity : _ Flambda_arity.t -> t list +val unknown_types_from_arity : [`Unarized] Flambda_arity.t -> t list (** For each of the kinds in an arity, create an "bottom" type. *) -val bottom_types_from_arity : _ Flambda_arity.t -> t list +val bottom_types_from_arity : [`Complex] Flambda_arity.t -> t list (** Whether the given type says that a term of that type can never be constructed (in other words, it is [Invalid]). *) diff --git a/middle_end/flambda2/types/grammar/more_type_creators.ml b/middle_end/flambda2/types/grammar/more_type_creators.ml index 664bd506f89..2c9d5783cbf 100644 --- a/middle_end/flambda2/types/grammar/more_type_creators.ml +++ b/middle_end/flambda2/types/grammar/more_type_creators.ml @@ -328,7 +328,8 @@ let rec unknown_with_subkind ?(alloc_mode = Alloc_mode.For_types.unknown ()) let bottom_with_subkind kind = bottom (Flambda_kind.With_subkind.kind kind) let unknown_types_from_arity arity = - List.map (unknown_with_subkind ?alloc_mode:None) (Flambda_arity.unarize arity) + List.map (unknown_with_subkind ?alloc_mode:None) + (Flambda_arity.unarized_components arity) let bottom_types_from_arity arity = List.map bottom_with_subkind (Flambda_arity.unarize arity) diff --git a/middle_end/flambda2/types/grammar/more_type_creators.mli b/middle_end/flambda2/types/grammar/more_type_creators.mli index fc05adaa47c..b32c7093121 100644 --- a/middle_end/flambda2/types/grammar/more_type_creators.mli +++ b/middle_end/flambda2/types/grammar/more_type_creators.mli @@ -149,7 +149,7 @@ val unknown_with_subkind : Type_grammar.t (** For each of the kinds in an arity, create an "unknown" type. *) -val unknown_types_from_arity : _ Flambda_arity.t -> Type_grammar.t list +val unknown_types_from_arity : [`Unarized] Flambda_arity.t -> Type_grammar.t list (** For each of the kinds in an arity, create an "bottom" type. *) -val bottom_types_from_arity : _ Flambda_arity.t -> Type_grammar.t list +val bottom_types_from_arity : [`Complex] Flambda_arity.t -> Type_grammar.t list From 442dade1554df2bd6a48df3159b37fab82feb1a2 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Thu, 11 May 2023 18:10:44 +0200 Subject: [PATCH 12/30] Fix tupled functions --- .../flambda2/from_lambda/closure_conversion.ml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/middle_end/flambda2/from_lambda/closure_conversion.ml b/middle_end/flambda2/from_lambda/closure_conversion.ml index 0e9eb0942a5..91af6558cc2 100644 --- a/middle_end/flambda2/from_lambda/closure_conversion.ml +++ b/middle_end/flambda2/from_lambda/closure_conversion.ml @@ -2228,8 +2228,17 @@ let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = contains_no_escaping_local_allocs ) -> ( let acc, _ = find_simples_and_arity acc env apply.args in let split_args = - let non_unarized_arity = arity in - let arity = Flambda_arity.unarize arity in + let non_unarized_arity, arity = + let arity = + if is_tupled + then + Flambda_arity.create_singletons + [ Flambda_kind.With_subkind.block Tag.zero + (Flambda_arity.unarize arity) ] + else arity + in + arity, Flambda_arity.unarize arity + in let split args arity = let rec cut n l = if n <= 0 @@ -2265,11 +2274,6 @@ let close_apply acc env (apply : IR.apply) : Expr_with_acc.t = remaining_arity } in - let arity = - if is_tupled - then [Flambda_kind.With_subkind.block Tag.zero arity] - else arity - in split apply.args arity in match split_args with From e778053d4f83387ddcbdc94690b203b44d8dca5e Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Fri, 12 May 2023 14:01:11 +0200 Subject: [PATCH 13/30] make fmt --- .../bound_identifiers/bound_parameters.mli | 2 +- .../flambda2/from_lambda/lambda_to_flambda.ml | 16 +++------ middle_end/flambda2/kinds/flambda_arity.ml | 4 +-- middle_end/flambda2/kinds/flambda_arity.mli | 6 ++-- .../flambda2/parser/flambda_to_fexpr.ml | 6 ++-- middle_end/flambda2/simplify/expr_builder.ml | 4 ++- .../flambda2/simplify/simplify_apply_expr.ml | 36 ++++++++----------- .../simplify/simplify_set_of_closures.ml | 3 +- middle_end/flambda2/terms/apply_expr.mli | 3 +- .../types/grammar/more_type_creators.ml | 3 +- .../types/grammar/more_type_creators.mli | 3 +- 11 files changed, 36 insertions(+), 50 deletions(-) diff --git a/middle_end/flambda2/bound_identifiers/bound_parameters.mli b/middle_end/flambda2/bound_identifiers/bound_parameters.mli index 9a9607f1637..9001ea45c73 100644 --- a/middle_end/flambda2/bound_identifiers/bound_parameters.mli +++ b/middle_end/flambda2/bound_identifiers/bound_parameters.mli @@ -30,7 +30,7 @@ val is_empty : t -> bool val same_number : t -> t -> bool -val arity : t -> [>] Flambda_arity.t +val arity : t -> [> ] Flambda_arity.t val check_no_duplicates : t -> unit diff --git a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml index 89f3453eed2..d8bd0097d95 100644 --- a/middle_end/flambda2/from_lambda/lambda_to_flambda.ml +++ b/middle_end/flambda2/from_lambda/lambda_to_flambda.ml @@ -55,17 +55,14 @@ module Env : sig val register_unboxed_product : t -> unboxed_product:Ident.t -> - before_unarization: - [`Complex] Flambda_arity.Component_for_creation.t -> + before_unarization:[`Complex] Flambda_arity.Component_for_creation.t -> fields:(Ident.t * Flambda_kind.With_subkind.t) list -> t val get_unboxed_product_fields : t -> Ident.t -> - ([`Complex] Flambda_arity.Component_for_creation.t - * Ident.t list) - option + ([`Complex] Flambda_arity.Component_for_creation.t * Ident.t list) option type add_continuation_result = private { body_env : t; @@ -1275,15 +1272,13 @@ type cps_continuation = | Non_tail of non_tail_continuation let apply_cps_cont_simple k ?(dbg = Debuginfo.none) acc env ccenv simples - (arity_component : - [`Complex] Flambda_arity.Component_for_creation.t) = + (arity_component : [`Complex] Flambda_arity.Component_for_creation.t) = match k with | Tail k -> apply_cont_with_extra_args acc env ccenv ~dbg k None simples | Non_tail k -> k acc env ccenv simples arity_component let apply_cps_cont k ?dbg acc env ccenv id - (arity_component : - [`Complex] Flambda_arity.Component_for_creation.t) = + (arity_component : [`Complex] Flambda_arity.Component_for_creation.t) = apply_cps_cont_simple k ?dbg acc env ccenv [IR.Var id] arity_component let maybe_insert_let_cont result_var_name layout k acc env ccenv body = @@ -1917,8 +1912,7 @@ and cps_non_tail_list : (* Always evaluate right-to-left. *) cps_non_tail_list_core acc env ccenv lams (fun acc env ccenv ids - (arity : - [`Complex] Flambda_arity.Component_for_creation.t list) -> + (arity : [`Complex] Flambda_arity.Component_for_creation.t list) -> k acc env ccenv (List.rev ids) (List.rev arity)) k_exn diff --git a/middle_end/flambda2/kinds/flambda_arity.ml b/middle_end/flambda2/kinds/flambda_arity.ml index 9810ac6171e..2e06cb1c2fe 100644 --- a/middle_end/flambda2/kinds/flambda_arity.ml +++ b/middle_end/flambda2/kinds/flambda_arity.ml @@ -60,9 +60,7 @@ module Component = struct | Unboxed_product ts -> List.concat_map unarize ts let component : [`Unarized] t -> Flambda_kind.With_subkind.t = - fun t -> - match t with - | Singleton kind -> kind + fun t -> match t with Singleton kind -> kind end type 'uc t = 'uc Component.t list diff --git a/middle_end/flambda2/kinds/flambda_arity.mli b/middle_end/flambda2/kinds/flambda_arity.mli index df939319477..8c67076d2fa 100644 --- a/middle_end/flambda2/kinds/flambda_arity.mli +++ b/middle_end/flambda2/kinds/flambda_arity.mli @@ -72,7 +72,8 @@ val unarize : [`Complex] t -> Flambda_kind.With_subkind.t list val unarized_components : [`Unarized] t -> Flambda_kind.With_subkind.t list (** Like [unarize] but returns one list per parameter. *) -val unarize_per_parameter : [`Complex] t -> Flambda_kind.With_subkind.t list list +val unarize_per_parameter : + [`Complex] t -> Flambda_kind.With_subkind.t list list (** Like [unarize] but returns a value of type [t]. *) val unarize_t : [`Complex] t -> [`Unarized] t @@ -92,4 +93,5 @@ val from_lambda_list : Lambda.layout list -> [`Complex] t (** Remove the first portion of an arity to correspond to a partial application. *) -val partially_apply : [`Complex] t -> num_non_unarized_params_provided:int -> [`Complex] t +val partially_apply : + [`Complex] t -> num_non_unarized_params_provided:int -> [`Complex] t diff --git a/middle_end/flambda2/parser/flambda_to_fexpr.ml b/middle_end/flambda2/parser/flambda_to_fexpr.ml index 03104a1f8a3..8e68f24cfcf 100644 --- a/middle_end/flambda2/parser/flambda_to_fexpr.ml +++ b/middle_end/flambda2/parser/flambda_to_fexpr.ml @@ -459,13 +459,11 @@ let is_default_arity (a : [`Unarized] Flambda_arity.t) = let complex_arity (a : [`Complex] Flambda_arity.t) : Fexpr.arity = (* CR mshinwell: add unboxed arities to Fexpr *) - Flambda_arity.unarize a - |> List.map kind_with_subkind + Flambda_arity.unarize a |> List.map kind_with_subkind let arity (a : [`Unarized] Flambda_arity.t) : Fexpr.arity = (* CR mshinwell: add unboxed arities to Fexpr *) - Flambda_arity.unarized_components a - |> List.map kind_with_subkind + Flambda_arity.unarized_components a |> List.map kind_with_subkind let arity_opt (a : [`Unarized] Flambda_arity.t) : Fexpr.arity option = if is_default_arity a then None else Some (arity a) diff --git a/middle_end/flambda2/simplify/expr_builder.ml b/middle_end/flambda2/simplify/expr_builder.ml index d593cc3eae7..939a7bb1147 100644 --- a/middle_end/flambda2/simplify/expr_builder.ml +++ b/middle_end/flambda2/simplify/expr_builder.ml @@ -746,7 +746,9 @@ let rewrite_fixed_arity_continuation0 uacc cont_or_apply_cont ~use_id arity : (fun _kind -> Variable.create "param") (Flambda_arity.unarized_components arity) in - let params = List.map2 BP.create params (Flambda_arity.unarized_components arity) in + let params = + List.map2 BP.create params (Flambda_arity.unarized_components arity) + in let args = List.map BP.simple params in let params = Bound_parameters.create params in let apply_cont = Apply_cont.create cont ~args ~dbg:Debuginfo.none in diff --git a/middle_end/flambda2/simplify/simplify_apply_expr.ml b/middle_end/flambda2/simplify/simplify_apply_expr.ml index 80e0fc0b68d..bfa80b56990 100644 --- a/middle_end/flambda2/simplify/simplify_apply_expr.ml +++ b/middle_end/flambda2/simplify/simplify_apply_expr.ml @@ -271,7 +271,9 @@ let simplify_direct_full_application ~simplify_expr dacc apply function_type arg)) denv params args in - let result_arity = Flambda_arity.unarized_components result_arity in + let result_arity = + Flambda_arity.unarized_components result_arity + in let denv = List.fold_left2 (fun denv kind result -> @@ -581,12 +583,10 @@ let simplify_direct_partial_application ~simplify_expr dacc apply Code.create code_id ~params_and_body ~free_names_of_params_and_body:free_names ~newer_version_of:None ~params_arity:(Bound_parameters.arity remaining_params) - ~num_trailing_local_params - ~result_arity:result_arity - ~result_types:Unknown ~contains_no_escaping_local_allocs ~stub:true - ~inline:Default_inline ~poll_attribute:Default - ~check:Check_attribute.Default_check ~is_a_functor:false ~recursive - ~cost_metrics:cost_metrics_of_body + ~num_trailing_local_params ~result_arity ~result_types:Unknown + ~contains_no_escaping_local_allocs ~stub:true ~inline:Default_inline + ~poll_attribute:Default ~check:Check_attribute.Default_check + ~is_a_functor:false ~recursive ~cost_metrics:cost_metrics_of_body ~inlining_arguments:(DE.inlining_arguments (DA.denv dacc)) ~dbg ~is_tupled:false ~is_my_closure_used: @@ -754,8 +754,7 @@ let simplify_direct_function_call ~simplify_expr dacc apply present on the application expression, so all we can do is check that the function being overapplied returns kind Value. *) if not - (Flambda_arity.equal_ignoring_subkinds - result_arity + (Flambda_arity.equal_ignoring_subkinds result_arity result_arity_of_application) then Misc.fatal_errorf @@ -791,10 +790,9 @@ let simplify_direct_function_call ~simplify_expr dacc apply Apply.print apply; simplify_direct_partial_application ~simplify_expr dacc apply ~callee's_code_id ~callee's_code_metadata ~callee's_function_slot - ~param_arity:params_arity ~args_arity - ~result_arity:result_arity - ~recursive ~down_to_up ~coming_from_indirect - ~closure_alloc_mode_from_type ~current_region + ~param_arity:params_arity ~args_arity ~result_arity ~recursive + ~down_to_up ~coming_from_indirect ~closure_alloc_mode_from_type + ~current_region ~num_trailing_local_non_unarized_params: (Code_metadata.num_trailing_local_params callee's_code_metadata)) else @@ -815,9 +813,7 @@ let rebuild_function_call_where_callee's_type_unavailable apply call_kind Unused_because_function_unknown) in let uacc, expr = - EB.rewrite_fixed_arity_apply uacc ~use_id - (Apply.return_arity apply) - apply + EB.rewrite_fixed_arity_apply uacc ~use_id (Apply.return_arity apply) apply in after_rebuild expr uacc @@ -993,9 +989,7 @@ let rebuild_method_call apply ~use_id ~exn_cont_use_id uacc ~after_rebuild = apply in let uacc, expr = - EB.rewrite_fixed_arity_apply uacc ~use_id - (Apply.return_arity apply) - apply + EB.rewrite_fixed_arity_apply uacc ~use_id (Apply.return_arity apply) apply in after_rebuild expr uacc @@ -1056,9 +1050,7 @@ let rebuild_c_call apply ~use_id ~exn_cont_use_id ~return_arity uacc let uacc, expr = match use_id with | Some use_id -> - EB.rewrite_fixed_arity_apply uacc ~use_id - return_arity - apply + EB.rewrite_fixed_arity_apply uacc ~use_id return_arity apply | None -> let uacc = UA.add_free_names uacc (Apply.free_names apply) diff --git a/middle_end/flambda2/simplify/simplify_set_of_closures.ml b/middle_end/flambda2/simplify/simplify_set_of_closures.ml index 1871a9134ed..a0b52ad64d0 100644 --- a/middle_end/flambda2/simplify/simplify_set_of_closures.ml +++ b/middle_end/flambda2/simplify/simplify_set_of_closures.ml @@ -175,8 +175,7 @@ let simplify_function_body context ~outer_dacc function_slot_opt assert (not (DE.at_unit_toplevel (DA.denv dacc))); match C.simplify_function_body context dacc body ~return_continuation - ~exn_continuation - ~return_arity:(Code.result_arity code) + ~exn_continuation ~return_arity:(Code.result_arity code) ~implicit_params: (Bound_parameters.create [ Bound_parameter.create my_closure diff --git a/middle_end/flambda2/terms/apply_expr.mli b/middle_end/flambda2/terms/apply_expr.mli index 3159218646a..73f0215e315 100644 --- a/middle_end/flambda2/terms/apply_expr.mli +++ b/middle_end/flambda2/terms/apply_expr.mli @@ -110,8 +110,7 @@ val with_continuations : t -> Result_continuation.t -> Exn_continuation.t -> t val with_exn_continuation : t -> Exn_continuation.t -> t (** Change the arguments of an application *) -val with_args : - t -> Simple.t list -> args_arity:[`Complex] Flambda_arity.t -> t +val with_args : t -> Simple.t list -> args_arity:[`Complex] Flambda_arity.t -> t (** Change the call kind of an application. *) val with_call_kind : t -> Call_kind.t -> t diff --git a/middle_end/flambda2/types/grammar/more_type_creators.ml b/middle_end/flambda2/types/grammar/more_type_creators.ml index 2c9d5783cbf..1dd88dd6a1a 100644 --- a/middle_end/flambda2/types/grammar/more_type_creators.ml +++ b/middle_end/flambda2/types/grammar/more_type_creators.ml @@ -328,7 +328,8 @@ let rec unknown_with_subkind ?(alloc_mode = Alloc_mode.For_types.unknown ()) let bottom_with_subkind kind = bottom (Flambda_kind.With_subkind.kind kind) let unknown_types_from_arity arity = - List.map (unknown_with_subkind ?alloc_mode:None) + List.map + (unknown_with_subkind ?alloc_mode:None) (Flambda_arity.unarized_components arity) let bottom_types_from_arity arity = diff --git a/middle_end/flambda2/types/grammar/more_type_creators.mli b/middle_end/flambda2/types/grammar/more_type_creators.mli index b32c7093121..65ca6e6fdb6 100644 --- a/middle_end/flambda2/types/grammar/more_type_creators.mli +++ b/middle_end/flambda2/types/grammar/more_type_creators.mli @@ -149,7 +149,8 @@ val unknown_with_subkind : Type_grammar.t (** For each of the kinds in an arity, create an "unknown" type. *) -val unknown_types_from_arity : [`Unarized] Flambda_arity.t -> Type_grammar.t list +val unknown_types_from_arity : + [`Unarized] Flambda_arity.t -> Type_grammar.t list (** For each of the kinds in an arity, create an "bottom" type. *) val bottom_types_from_arity : [`Complex] Flambda_arity.t -> Type_grammar.t list From 02d2a0cd288c83ccf0aa09e26ef5150fb530a5e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABlle=20Courant?= Date: Tue, 30 May 2023 13:39:42 +0200 Subject: [PATCH 14/30] Restore typing hack --- ocaml/typing/predef.ml | 56 +++++++++++++++++++++++++++++++++++++++++ ocaml/typing/typeopt.ml | 13 +++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/ocaml/typing/predef.ml b/ocaml/typing/predef.ml index 30b5b1d0161..b210cf253ad 100644 --- a/ocaml/typing/predef.ml +++ b/ocaml/typing/predef.ml @@ -196,6 +196,55 @@ let common_initial_env add_type add_extension empty_env = } in add_type type_ident decl env + and add_type2 type_ident + ?(kind=fun _ -> Type_abstract) + ?(layout=Layout.value) + ~variance ~separability env = + let param0 = newgenvar Layout.value in + let param1 = newgenvar Layout.value in + let decl = + {type_params = [param0; param1]; + type_arity = 2; + type_kind = kind param0; + type_layout = layout; + type_loc = Location.none; + type_private = Asttypes.Public; + type_manifest = None; + type_variance = [variance; variance]; + type_separability = [separability; separability]; + type_is_newtype = false; + type_expansion_scope = lowest_level; + type_attributes = []; + type_unboxed_default = false; + type_uid = Uid.of_predef_id type_ident; + } + in + add_type type_ident decl env + and add_type3 type_ident + ?(kind=fun _ -> Type_abstract) + ?(layout=Layout.value) + ~variance ~separability env = + let param0 = newgenvar Layout.value in + let param1 = newgenvar Layout.value in + let param2 = newgenvar Layout.value in + let decl = + {type_params = [param0; param1; param2]; + type_arity = 3; + type_kind = kind param0; + type_layout = layout; + type_loc = Location.none; + type_private = Asttypes.Public; + type_manifest = None; + type_variance = [variance; variance; variance]; + type_separability = [separability; separability; separability]; + type_is_newtype = false; + type_expansion_scope = lowest_level; + type_attributes = []; + type_unboxed_default = false; + type_uid = Uid.of_predef_id type_ident; + } + in + add_type type_ident decl env in let add_extension id args layouts = add_extension id @@ -261,6 +310,13 @@ let common_initial_env add_type add_extension empty_env = |> add_type ident_unit ~kind:(variant [cstr ident_void []] [| [| |] |]) ~layout:(Layout.immediate ~why:Enumeration) + |> add_type2 ident_unboxed_pair + ~variance:Variance.covariant + ~separability:Separability.Ind + |> add_type3 ident_unboxed_triple + ~variance:Variance.covariant + ~separability:Separability.Ind + |> add_type ident_real_void (* Predefined exceptions - alphabetical order *) |> add_extension ident_assert_failure [newgenty (Ttuple[type_string; type_int; type_int])] diff --git a/ocaml/typing/typeopt.ml b/ocaml/typing/typeopt.ml index 1b6c67c8999..86c501f940c 100644 --- a/ocaml/typing/typeopt.ml +++ b/ocaml/typing/typeopt.ml @@ -486,7 +486,18 @@ let value_kind env loc ty = (* CR layouts v2: We'll have other layouts. Think about what to do with the sanity check in value_kind. *) -let layout env loc ty = Lambda.Pvalue (value_kind env loc ty) +let rec layout env loc ty = + match get_desc (scrape_ty env ty) with + | Tconstr(p, args, _) when Path.same p Predef.path_unboxed_pair -> + let layouts = List.map (layout env loc) args in + Punboxed_product layouts + | Tconstr(p, args, _) when Path.same p Predef.path_unboxed_triple -> + let layouts = List.map (layout env loc) args in + Punboxed_product layouts + | Tconstr(p, _, _) when Path.same p Predef.path_void -> + Punboxed_product [] + | _ -> + Lambda.Pvalue (value_kind env loc ty) let function_return_layout env loc ty = match is_function_type env ty with From cfc85a914b75d083a1b9ce95c5dfcc55e292f54f Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Mon, 3 Apr 2023 11:55:06 +0200 Subject: [PATCH 15/30] Start flambda1 unboxed_tuple in cmmgen --- backend/cmm.ml | 1 + backend/cmm.mli | 1 + backend/cmmgen.ml | 76 ++++++++++++++++++++++++++- backend/printcmm.ml | 2 + backend/selectgen.ml | 10 ++++ middle_end/clambda_primitives.ml | 3 ++ middle_end/clambda_primitives.mli | 3 ++ middle_end/convert_primitives.ml | 5 +- middle_end/printclambda_primitives.ml | 14 +++++ middle_end/semantics_of_primitives.ml | 4 ++ 10 files changed, 115 insertions(+), 4 deletions(-) diff --git a/backend/cmm.ml b/backend/cmm.ml index 7812285de45..6c20cff4c00 100644 --- a/backend/cmm.ml +++ b/backend/cmm.ml @@ -217,6 +217,7 @@ and operation = | Cprobe_is_enabled of { name: string } | Copaque | Cbeginregion | Cendregion + | Ctuple_field of int * machtype type kind_for_unboxing = | Any diff --git a/backend/cmm.mli b/backend/cmm.mli index 244f50b7b86..cb912ca9f6a 100644 --- a/backend/cmm.mli +++ b/backend/cmm.mli @@ -219,6 +219,7 @@ and operation = | Cprobe_is_enabled of { name: string } | Copaque (* Sys.opaque_identity *) | Cbeginregion | Cendregion + | Ctuple_field of int * machtype (* This is information used exclusively during construction of cmm terms by cmmgen, and thus irrelevant for selectgen and flambda2. *) diff --git a/backend/cmmgen.ml b/backend/cmmgen.ml index 80106aead77..4e83f0065fa 100644 --- a/backend/cmmgen.ml +++ b/backend/cmmgen.ml @@ -436,6 +436,36 @@ let rec is_unboxed_number_cmm = function (is_unboxed_number_cmm body) (List.map (fun (_, _, e, _) -> is_unboxed_number_cmm e) handlers) +type layout_atom = + | LValue + | Lunboxed_float + | Lunboxed_int of Lambda.boxed_integer + +let rec take_n n l = + if n <= 0 then [] + else + match l with + | [] -> assert false + | h :: t -> h :: (take_n (n-1) t) + +let rec flatten_layout (layout : Lambda.layout) = + match layout with + | Ptop -> assert false + | Pbottom -> [] + | Pvalue _ -> [LValue] + | Punboxed_float -> [Lunboxed_float] + | Punboxed_int b -> [Lunboxed_int b] + | Punboxed_product l -> + List.flatten (List.map flatten_layout l) + +let layout_machtype (atom : layout_atom) = + match atom with + | LValue -> typ_val + | Lunboxed_float -> typ_float + | Lunboxed_int _ -> + (* Only 64-bit architectures, so this is always [typ_int] *) + typ_int + (* Translate an expression *) let rec transl env e = @@ -578,6 +608,27 @@ let rec transl env e = (* Primitives *) | Uprim(prim, args, dbg) -> begin match (simplif_primitive prim, args) with + + | (Pmake_unboxed_product layouts, args) -> + let rec loop offset args layouts acc = + match args, layouts with + | [], [] -> + Ctuple acc + | [], _ | _, [] -> assert false + | arg :: args, layout :: layouts -> + let arg = transl env arg in + bind "arg" arg (fun arg -> + let layout = flatten_layout layout in + let skip = List.length layout in + let loads = + List.mapi (fun i layout -> + Cop (Ctuple_field (i,(layout_machtype layout)) , [arg], dbg)) + layout + in + loop (offset + skip) args layouts (loads @ acc) + ) + in + loop 0 (List.rev args) (List.rev layouts) [] | (Pread_symbol sym, []) -> Cconst_symbol (global_symbol sym, dbg) | (Pmakeblock _, []) -> @@ -685,7 +736,8 @@ let rec transl env e = | Pasrbint _ | Pbintcomp (_, _) | Pstring_load _ | Pbytes_load _ | Pbytes_set _ | Pbigstring_load _ | Pbigstring_set _ | Punbox_float | Pbox_float _ | Punbox_int _ | Pbox_int _ - | Pbbswap _), _) + | Pbbswap _ + | Punboxed_product_field _), _) -> fatal_error "Cmmgen.transl:prim" end @@ -997,6 +1049,20 @@ and transl_prim_1 env p arg dbg = | Pbswap16 -> tag_int (bswap16 (ignore_high_bit_int (untag_int (transl env arg) dbg)) dbg) dbg + | Punboxed_product_field (field, layouts) -> + Cmm_helpers.bind "unboxed_product" (transl env arg) (fun arg -> + let prev_layouts = + List.map flatten_layout (take_n field layouts) |> + List.flatten + in + let skip = List.length prev_layouts in + let layout = List.nth layouts field in + let loads = + List.mapi (fun i layout -> + Cop (Ctuple_field (skip + i, layout_machtype layout), [arg], dbg)) + (flatten_layout layout) + in + Ctuple loads) | (Pfield_computed | Psequand | Psequor | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint @@ -1013,7 +1079,9 @@ and transl_prim_1 env p arg dbg = | Plslbint _ | Plsrbint _ | Pasrbint _ | Pbintcomp (_, _) | Pbigarrayref (_, _, _, _) | Pbigarrayset (_, _, _, _) | Pbigarraydim _ | Pstring_load _ | Pbytes_load _ | Pbytes_set _ - | Pbigstring_load _ | Pbigstring_set _ | Pprobe_is_enabled _) + | Pbigstring_load _ | Pbigstring_set _ | Pprobe_is_enabled _ + | Pmake_unboxed_product _ + ) -> fatal_errorf "Cmmgen.transl_prim_1: %a" Printclambda_primitives.primitive p @@ -1193,6 +1261,8 @@ and transl_prim_2 env p arg1 arg2 dbg = | Pbigarraydim _ | Pbytes_set _ | Pbigstring_set _ | Pbbswap _ | Pprobe_is_enabled _ | Punbox_float | Pbox_float _ | Punbox_int _ | Pbox_int _ + | Pmake_unboxed_product _ + | Punboxed_product_field _ -> fatal_errorf "Cmmgen.transl_prim_2: %a" Printclambda_primitives.primitive p @@ -1254,6 +1324,8 @@ and transl_prim_3 env p arg1 arg2 arg3 dbg = | Pstring_load _ | Pbytes_load _ | Pbigstring_load _ | Pbbswap _ | Pprobe_is_enabled _ | Punbox_float | Pbox_float _ | Punbox_int _ | Pbox_int _ + | Pmake_unboxed_product _ + | Punboxed_product_field _ -> fatal_errorf "Cmmgen.transl_prim_3: %a" Printclambda_primitives.primitive p diff --git a/backend/printcmm.ml b/backend/printcmm.ml index 0b1e84e643e..f1ce5767f94 100644 --- a/backend/printcmm.ml +++ b/backend/printcmm.ml @@ -237,6 +237,8 @@ let operation d = function | Copaque -> "opaque" | Cbeginregion -> "beginregion" | Cendregion -> "endregion" + | Ctuple_field (field, _ty) -> + to_string "tuple_field %i" field let rec expr ppf = function diff --git a/backend/selectgen.ml b/backend/selectgen.ml index a985ef98a24..7d7c55a1307 100644 --- a/backend/selectgen.ml +++ b/backend/selectgen.ml @@ -228,6 +228,7 @@ let oper_result_type = function naked pointer into the local allocation stack. *) typ_int | Cendregion -> typ_void + | Ctuple_field (_, ty) -> ty (* Infer the size in bytes of the result of an expression whose evaluation may be deferred (cf. [emit_parts]). *) @@ -499,6 +500,7 @@ method is_simple_expr = function | Ccsel _ | Cabsf | Caddf | Csubf | Cmulf | Cdivf | Cfloatofint | Cintoffloat | Cvalueofint | Cintofvalue + | Ctuple_field _ | Ccmpf _ -> List.for_all self#is_simple_expr args end | Cassign _ | Cifthenelse _ | Cswitch _ | Ccatch _ | Cexit _ @@ -546,6 +548,7 @@ method effects_of exp = | Cload (_, Asttypes.Immutable) -> EC.none | Cload (_, Asttypes.Mutable) -> EC.coeffect_only Coeffect.Read_mutable | Cprobe_is_enabled _ -> EC.coeffect_only Coeffect.Arbitrary + | Ctuple_field _ | Caddi | Csubi | Cmuli | Cmulhi _ | Cdivi | Cmodi | Cand | Cor | Cxor | Cbswap _ | Ccsel _ @@ -917,6 +920,13 @@ method emit_expr_aux (env:environment) exp : let rs = self#emit_tuple env simple_args in ret (self#insert_op_debug env Iopaque dbg rs rs) end + | Cop(Ctuple_field(field, _layout), [arg], dbg) -> + begin match self#emit_expr env arg with + None -> None + | Some loc_exp -> + (* All fields are of size one *) + Some [|loc_exp.(field)|] + end | Cop(op, args, dbg) -> begin match self#emit_parts_list env args with None -> None diff --git a/middle_end/clambda_primitives.ml b/middle_end/clambda_primitives.ml index b0b731993c7..56ba8d23484 100644 --- a/middle_end/clambda_primitives.ml +++ b/middle_end/clambda_primitives.ml @@ -126,6 +126,9 @@ type primitive = | Pbox_float of alloc_mode | Punbox_int of boxed_integer | Pbox_int of boxed_integer * alloc_mode + (* Unboxed products *) + | Pmake_unboxed_product of layout list + | Punboxed_product_field of int * (layout list) and integer_comparison = Lambda.integer_comparison = Ceq | Cne | Clt | Cgt | Cle | Cge diff --git a/middle_end/clambda_primitives.mli b/middle_end/clambda_primitives.mli index 5e3ddfd0765..609a4f8d2fb 100644 --- a/middle_end/clambda_primitives.mli +++ b/middle_end/clambda_primitives.mli @@ -129,6 +129,9 @@ type primitive = | Pbox_float of alloc_mode | Punbox_int of boxed_integer | Pbox_int of boxed_integer * alloc_mode + (* Unboxed products *) + | Pmake_unboxed_product of layout list + | Punboxed_product_field of int * (layout list) and integer_comparison = Lambda.integer_comparison = Ceq | Cne | Clt | Cgt | Cle | Cge diff --git a/middle_end/convert_primitives.ml b/middle_end/convert_primitives.ml index 9180f67f359..0c8f8435d30 100644 --- a/middle_end/convert_primitives.ml +++ b/middle_end/convert_primitives.ml @@ -38,8 +38,9 @@ let convert (prim : Lambda.primitive) : Clambda_primitives.primitive = | Psetfloatfield (field, init_or_assign) -> Psetfloatfield (field, init_or_assign) | Pduprecord (repr, size) -> Pduprecord (repr, size) - | Pmake_unboxed_product _ - | Punboxed_product_field _ -> Misc.fatal_error "TODO" + | Pmake_unboxed_product layouts -> Pmake_unboxed_product layouts + | Punboxed_product_field (field, layouts) -> + Punboxed_product_field (field, layouts) | Pccall prim -> Pccall prim | Praise kind -> Praise kind | Psequand -> Psequand diff --git a/middle_end/printclambda_primitives.ml b/middle_end/printclambda_primitives.ml index f8762b18c4f..de7b6d694e7 100644 --- a/middle_end/printclambda_primitives.ml +++ b/middle_end/printclambda_primitives.ml @@ -235,3 +235,17 @@ let primitive ppf (prim:Clambda_primitives.primitive) = | Pbox_int (bi, m) -> fprintf ppf "box_%s.%s" (boxed_integer_name bi) (alloc_kind m) | Punbox_int bi -> fprintf ppf "unbox_%s" (boxed_integer_name bi) + | Pmake_unboxed_product layouts -> + fprintf ppf "make_unboxed_product(@[%a@])" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") + Printlambda.layout) + layouts + | Punboxed_product_field (field, layouts) -> + fprintf ppf "unboxed_product_field(@[%a@]) %i" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") + Printlambda.layout) + layouts + field + diff --git a/middle_end/semantics_of_primitives.ml b/middle_end/semantics_of_primitives.ml index d1ffb1c0ebf..c63d36db751 100644 --- a/middle_end/semantics_of_primitives.ml +++ b/middle_end/semantics_of_primitives.ml @@ -83,6 +83,8 @@ let for_primitive (prim : Clambda_primitives.primitive) = | Poffsetint _ -> No_effects, No_coeffects | Poffsetref _ -> Arbitrary_effects, Has_coeffects | Punbox_float | Punbox_int _ + | Pmake_unboxed_product _ + | Punboxed_product_field _ | Pintoffloat | Pfloatcomp _ -> No_effects, No_coeffects | Pbox_float m | Pbox_int (_, m) @@ -213,6 +215,8 @@ let may_locally_allocate (prim:Clambda_primitives.primitive) : bool = | Poffsetint _ -> false | Poffsetref _ -> false | Punbox_float | Punbox_int _ + | Pmake_unboxed_product _ + | Punboxed_product_field _ | Pintoffloat | Pfloatcomp _ -> false | Pbox_float m | Pbox_int (_, m) From 52093e602b46df0c569b046f47626b38251c88a9 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Mon, 3 Apr 2023 20:51:19 +0200 Subject: [PATCH 16/30] Missing case in proc --- backend/amd64/proc.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/amd64/proc.ml b/backend/amd64/proc.ml index c58a01f0563..e4cc9d37e64 100644 --- a/backend/amd64/proc.ml +++ b/backend/amd64/proc.ml @@ -559,6 +559,7 @@ let operation_supported = function | Craise _ | Ccheckbound | Cprobe _ | Cprobe_is_enabled _ | Copaque | Cbeginregion | Cendregion + | Ctuple_field _ -> true let trap_size_in_bytes = 16 From 04510d5ab7479105ee24cba74a6237719ac45f99 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Mon, 3 Apr 2023 20:51:50 +0200 Subject: [PATCH 17/30] TMP layout_decomposition --- middle_end/flambda/closure_offsets.ml | 177 +++++++++++++++++++---- middle_end/flambda/closure_offsets.mli | 16 +- middle_end/flambda/export_info.ml | 9 +- middle_end/flambda/export_info.mli | 8 +- middle_end/flambda/flambda_to_clambda.ml | 56 +++++-- 5 files changed, 209 insertions(+), 57 deletions(-) diff --git a/middle_end/flambda/closure_offsets.ml b/middle_end/flambda/closure_offsets.ml index 11f071656ec..a0e3dbf2654 100644 --- a/middle_end/flambda/closure_offsets.ml +++ b/middle_end/flambda/closure_offsets.ml @@ -16,11 +16,143 @@ [@@@ocaml.warning "+a-4-9-30-40-41-42"] +type layout_atom = + | Value + | Value_int + | Unboxed_float + | Unboxed_int of Lambda.boxed_integer + +type ('visible, 'invisible) decomposition' = + | Gc_visible of ('visible * layout_atom) + | Gc_invisible of ('invisible * layout_atom) + | Product of ('visible, 'invisible) decomposition' array + +type decomposition = + | Atom of (int * layout_atom) + | Product of decomposition array +type parts = decomposition + +let equal_parts (p1 : parts) p2 = p1 = p2 +let print_parts ppf _p = + Format.fprintf ppf "TODO offset parts" + type result = { function_offsets : int Closure_id.Map.t; - free_variable_offsets : int Var_within_closure.Map.t; + free_variable_offsets : parts Var_within_closure.Map.t; } +let rec decompose (layout : Lambda.layout) : _ decomposition' = + match layout with + | Ptop -> + Misc.fatal_error "[Ptop] can't be stored in a closure." + | Pbottom -> + Misc.fatal_error + "[Pbottom] should have been eliminated as dead code \ + and not stored in a closure." + | Punboxed_float -> Gc_invisible ((), Unboxed_float) + | Punboxed_int bi -> Gc_invisible ((), Unboxed_int bi) + | Pvalue Pintval -> Gc_invisible ((), Value_int) + | Pvalue _ -> Gc_visible ((), Value) + | Punboxed_product l -> + Product (Array.of_list (List.map decompose l)) + +let rec solidify (dec : (int, int) decomposition') : decomposition = + match dec with + | Gc_visible (off, layout) -> Atom (off, layout) + | Gc_invisible (off, layout) -> Atom (off, layout) + | Product a -> + Product (Array.map solidify a) + +let rec fold_decompose + (f1 : 'acc -> 'a -> layout_atom -> 'acc * 'b) (f2 : 'acc -> 'c -> layout_atom -> 'acc * 'd) + (acc : 'acc) (d : ('a, 'c) decomposition') : + 'acc * ('b, 'd) decomposition' = + match d with + | Gc_visible (v, layout) -> + let acc, v = f1 acc v layout in + acc, Gc_visible (v, layout) + | Gc_invisible (v, layout) -> + let acc, v = f2 acc v layout in + acc, Gc_invisible (v, layout) + | Product elts -> + let acc, elts = Array.fold_left_map (fold_decompose f1 f2) acc elts in + acc, Product elts + +let layout_atom_size (layout : layout_atom) = + match layout with + | Value + | Value_int + | Unboxed_float + | Unboxed_int _ -> 1 + +let assign_visible_offsets init_pos (var, dec) = + let f_visible acc () layout = + acc + layout_atom_size layout, acc + in + let f_invisible acc () _layout = + acc, () + in + let acc, dec = fold_decompose f_visible f_invisible init_pos dec in + acc, (var, dec) + +let assign_invisible_offsets init_pos (var, dec) = + let f_visible acc off _layout = + acc, off + in + let f_invisible acc () layout = + acc + layout_atom_size layout, acc + in + let acc, dec = fold_decompose f_visible f_invisible init_pos dec in + acc, (var, solidify dec) + +(* let rec layout_size (layout : Lambda.layout) = *) +(* match layout with *) +(* | Ptop -> *) +(* Misc.fatal_error "[Ptop] can't be stored in a closure." *) +(* | Pbottom -> *) +(* Misc.fatal_error *) +(* "[Pbottom] should have been eliminated as dead code \ *) +(* and not stored in a closure." *) +(* | Punboxed_float *) +(* | Punboxed_int _ *) +(* | Pvalue Pintval *) +(* | Pvalue _ -> 1 *) +(* | Punboxed_product l -> *) +(* List.fold_left (fun acc e -> acc + layout_size e) 0 l *) +(* let _ = ignore layout_size *) + +(* let split_scannable layout = *) +(* let rec loop (layout : Lambda.layout) path = *) +(* match layout with *) +(* | Ptop -> *) +(* Misc.fatal_error "[Ptop] can't be stored in a closure." *) +(* | Pbottom -> *) +(* Misc.fatal_error *) +(* "[Pbottom] should have been eliminated as dead code \ *) +(* and not stored in a closure." *) +(* | Punboxed_float -> { gc_invisible = [Unboxed_float, path]; gc_visible = [] } *) +(* | Punboxed_int bi -> { gc_invisible = [Unboxed_int bi, path]; gc_visible = [] } *) +(* | Pvalue Pintval -> { gc_invisible = [Value_int, path]; gc_visible = [] } *) +(* | Pvalue _ -> { gc_invisible = []; gc_visible = [Value, path] } *) +(* | Punboxed_product l -> *) +(* let splits = List.mapi (fun i layout -> loop layout (i :: path)) l in *) +(* let merged = *) +(* List.fold_left (fun { gc_invisible; gc_visible } e -> *) +(* { gc_invisible = e.gc_invisible @ gc_invisible; *) +(* gc_visible = e.gc_visible @ gc_visible; }) *) +(* { gc_invisible = []; gc_visible = [] } splits *) +(* in *) +(* (\* match merged.gc_invisible with *\) *) +(* (\* | [] -> { gc_invisible = []; gc_visible = [layout, path] } *\) *) +(* (\* | _ -> *\) *) +(* (\* match merged.gc_visible with *\) *) +(* (\* | [] -> { gc_visible = []; gc_invisible = [layout, path] } *\) *) +(* (\* | _ -> *\) *) +(* merged *) +(* in *) +(* loop layout [] *) + + let add_closure_offsets { function_offsets; free_variable_offsets } ({ function_decls; free_vars } : Flambda.set_of_closures) = @@ -58,39 +190,20 @@ let add_closure_offsets accesses. *) (* CR-someday mshinwell: As discussed with lwhite, maybe this isn't ideal, and the self accesses should be explicitly marked too. *) - let assign_free_variable_offset var _ (map, pos) = - let var_within_closure = Var_within_closure.wrap var in - if Var_within_closure.Map.mem var_within_closure map then begin - Misc.fatal_errorf "Closure_offsets.add_closure_offsets: free variable \ - offset for %a would be defined multiple times" - Var_within_closure.print var_within_closure - end; - let map = Var_within_closure.Map.add var_within_closure pos map in - (map, pos + 1) - in - let gc_invisible_free_vars, gc_visible_free_vars = - Variable.Map.partition (fun _ (free_var : Flambda.specialised_to) -> - match free_var.kind with - | Ptop -> - Misc.fatal_error "[Ptop] can't be stored in a closure." - | Pbottom -> - Misc.fatal_error - "[Pbottom] should have been eliminated as dead code \ - and not stored in a closure." - | Punboxed_float -> true - | Punboxed_int _ -> true - | Pvalue Pintval -> true - | Pvalue _ -> false - | Punboxed_product _ -> Misc.fatal_error "TODO") - free_vars + let free_vars = Variable.Map.bindings free_vars in + let free_vars = List.map (fun (var, (free_var : Flambda.specialised_to)) -> + var, decompose free_var.kind) free_vars in + let free_variable_pos, free_vars = + List.fold_left_map assign_visible_offsets free_variable_pos free_vars in - let free_variable_offsets, free_variable_pos = - Variable.Map.fold assign_free_variable_offset - gc_invisible_free_vars (free_variable_offsets, free_variable_pos) + let _free_variable_pos, free_vars = + List.fold_left_map assign_invisible_offsets free_variable_pos free_vars in - let free_variable_offsets, _ = - Variable.Map.fold assign_free_variable_offset - gc_visible_free_vars (free_variable_offsets, free_variable_pos) + let free_variable_offsets = + List.fold_left (fun map (var, dec) -> + let var_within_closure = Var_within_closure.wrap var in + Var_within_closure.Map.add var_within_closure dec map) + free_variable_offsets free_vars in { function_offsets; free_variable_offsets; diff --git a/middle_end/flambda/closure_offsets.mli b/middle_end/flambda/closure_offsets.mli index 7ecf9c276d2..a0c7fe94538 100644 --- a/middle_end/flambda/closure_offsets.mli +++ b/middle_end/flambda/closure_offsets.mli @@ -19,9 +19,23 @@ (** Assign numerical offsets, within closure blocks, for code pointers and environment entries. *) +type layout_atom = + | Value + | Value_int + | Unboxed_float + | Unboxed_int of Lambda.boxed_integer + +type decomposition = + | Atom of (int * layout_atom) + | Product of decomposition array +type parts = decomposition + +val equal_parts : parts -> parts -> bool +val print_parts : Format.formatter -> parts -> unit + type result = private { function_offsets : int Closure_id.Map.t; - free_variable_offsets : int Var_within_closure.Map.t; + free_variable_offsets : parts Var_within_closure.Map.t; } val compute : Flambda.program -> result diff --git a/middle_end/flambda/export_info.ml b/middle_end/flambda/export_info.ml index 510a6f4b252..dffd12dc98e 100644 --- a/middle_end/flambda/export_info.ml +++ b/middle_end/flambda/export_info.ml @@ -142,7 +142,7 @@ type t = { values : descr Export_id.Map.t Compilation_unit.Map.t; symbol_id : Export_id.t Symbol.Map.t; offset_fun : int Closure_id.Map.t; - offset_fv : int Var_within_closure.Map.t; + offset_fv : Closure_offsets.parts Var_within_closure.Map.t; constant_closures : Closure_id.Set.t; invariant_params : Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t; recursive : Variable.Set.t Set_of_closures_id.Map.t; @@ -291,7 +291,7 @@ let merge (t1 : t) (t2 : t) : t = offset_fun = Closure_id.Map.disjoint_union ~eq:int_eq t1.offset_fun t2.offset_fun; offset_fv = Var_within_closure.Map.disjoint_union - ~eq:int_eq t1.offset_fv t2.offset_fv; + ~eq:Closure_offsets.equal_parts t1.offset_fv t2.offset_fv; constant_closures = Closure_id.Set.union t1.constant_closures t2.constant_closures; invariant_params = @@ -544,8 +544,9 @@ let print_offsets ppf (t : t) = Closure_id.print cid off) t.offset_fun; Format.fprintf ppf "@]@ @[offset_fv:@ "; Var_within_closure.Map.iter (fun vid off -> - Format.fprintf ppf "%a -> %i@ " - Var_within_closure.print vid off) t.offset_fv; + Format.fprintf ppf "%a -> %a@ " + Var_within_closure.print vid + Closure_offsets.print_parts off) t.offset_fv; Format.fprintf ppf "@]@ " let print_functions ppf (t : t) = diff --git a/middle_end/flambda/export_info.mli b/middle_end/flambda/export_info.mli index 6b53dd75ea5..a70b894e95a 100644 --- a/middle_end/flambda/export_info.mli +++ b/middle_end/flambda/export_info.mli @@ -87,7 +87,7 @@ type t = private { (** Associates symbols and values. *) offset_fun : int Closure_id.Map.t; (** Positions of function pointers in their closures. *) - offset_fv : int Var_within_closure.Map.t; + offset_fv : Closure_offsets.parts Var_within_closure.Map.t; (** Positions of value pointers in their closures. *) constant_closures : Closure_id.Set.t; (* CR-soon mshinwell for pchambart: Add comment *) @@ -123,7 +123,7 @@ val create -> values:descr Export_id.Map.t Compilation_unit.Map.t -> symbol_id:Export_id.t Symbol.Map.t -> offset_fun:int Closure_id.Map.t - -> offset_fv:int Var_within_closure.Map.t + -> offset_fv:Closure_offsets.parts Var_within_closure.Map.t -> constant_closures:Closure_id.Set.t -> invariant_params:Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t -> recursive:Variable.Set.t Set_of_closures_id.Map.t @@ -154,9 +154,9 @@ val t_of_transient : transient -> program: Flambda.program -> local_offset_fun:int Closure_id.Map.t - -> local_offset_fv:int Var_within_closure.Map.t + -> local_offset_fv:Closure_offsets.parts Var_within_closure.Map.t -> imported_offset_fun:int Closure_id.Map.t - -> imported_offset_fv:int Var_within_closure.Map.t + -> imported_offset_fv:Closure_offsets.parts Var_within_closure.Map.t -> constant_closures:Closure_id.Set.t -> t diff --git a/middle_end/flambda/flambda_to_clambda.ml b/middle_end/flambda/flambda_to_clambda.ml index a5be4f92237..a48db8db27a 100644 --- a/middle_end/flambda/flambda_to_clambda.ml +++ b/middle_end/flambda/flambda_to_clambda.ml @@ -22,7 +22,7 @@ module Int = Misc.Stdlib.Int type 'a for_one_or_more_units = { fun_offset_table : int Closure_id.Map.t; - fv_offset_table : int Var_within_closure.Map.t; + fv_offset_table : Closure_offsets.parts Var_within_closure.Map.t; constant_closures : Closure_id.Set.t; closures: Closure_id.Set.t; } @@ -244,6 +244,23 @@ let to_clambda_const env (const : Flambda.constant_defining_value_block_field) | Const (Int i) -> Uconst_int i | Const (Char c) -> Uconst_int (Char.code c) +let layout_of_atom (atom : Closure_offsets.layout_atom) : Lambda.layout = + match atom with + | Value -> Pvalue Pgenval + | Value_int -> Pvalue Pintval + | Unboxed_float -> Punboxed_float + | Unboxed_int bi -> Punboxed_int bi + +let load_var_field ~fun_offset ~check_field (parts : Closure_offsets.parts) : Clambda.ulambda = + match parts with + (* | [] -> failwith "TODO void" *) + | Atom (var_offset, layout) -> + let pos = var_offset - fun_offset in + Uprim (Pfield (pos, layout_of_atom layout), + [check_field pos], + Debuginfo.none) + | _ -> failwith "TODO multiple parts" + let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda * Lambda.layout = match flam with | Var var -> subst_var env var @@ -499,16 +516,16 @@ and to_clambda_named t env var (named : Flambda.named) : Clambda.ulambda * Lambd ((get_fun_offset t move_to) - (get_fun_offset t start_from))) named, Lambda.layout_function - | Project_var { closure; var; closure_id; kind } -> - let ulam, _closure_layout = subst_var env closure in - let fun_offset = get_fun_offset t closure_id in - let var_offset = get_fv_offset t var in - let pos = var_offset - fun_offset in - Uprim (Pfield (pos, kind), - [check_field t (check_closure t ulam (Expr (Var closure))) - pos (Some named)], - Debuginfo.none), - kind + | Project_var { closure; var; closure_id; kind } -> begin + let ulam, _closure_layout = subst_var env closure in + let fun_offset = get_fun_offset t closure_id in + let var_offset = get_fv_offset t var in + let check_field pos = + check_field t (check_closure t ulam (Expr (Var closure))) + pos (Some named) + in + load_var_field ~fun_offset ~check_field var_offset, kind + end | Prim (Pfield (index, layout), [block], dbg) -> begin match layout with | Pvalue _ -> () @@ -655,10 +672,14 @@ and to_clambda_set_of_closures t env Variable.print id Flambda.print_set_of_closures set_of_closures in - let pos = var_offset - fun_offset in - Env.add_subst env id - (Uprim (Pfield (pos, spec_to.kind), [Clambda.Uvar env_var], Debuginfo.none)) - spec_to.kind + match var_offset with + (* | [] -> failwith "TODO void closure building" *) + | Atom (var_offset, _layout) -> + let pos = var_offset - fun_offset in + Env.add_subst env id + (Uprim (Pfield (pos, spec_to.kind), [Clambda.Uvar env_var], Debuginfo.none)) + spec_to.kind + | _ -> failwith "TODO multiple parts closure building" in let env = Variable.Map.fold add_env_free_variable free_vars env in (* Add the Clambda expressions for all functions defined in the current @@ -714,7 +735,10 @@ and to_clambda_set_of_closures t env | Punboxed_int _ -> true | Pvalue Pintval -> true | Pvalue _ -> false - | Punboxed_product _ -> Misc.fatal_error "TBD") + | Punboxed_product _ -> + true + (* Misc.fatal_error "TBD" *) + ) free_vars in let to_closure_args free_vars = From f30211e4f4b4af0aac98f2bfd58b8b76242f0c95 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Wed, 5 Apr 2023 14:46:14 +0200 Subject: [PATCH 18/30] Various adds to unarize if --- backend/cmmgen.ml | 2 +- middle_end/clambda_primitives.ml | 2 ++ middle_end/printclambda.ml | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/cmmgen.ml b/backend/cmmgen.ml index 4e83f0065fa..d8a97cf1cf2 100644 --- a/backend/cmmgen.ml +++ b/backend/cmmgen.ml @@ -1399,6 +1399,7 @@ and transl_let env str (layout : Lambda.layout) id exp transl_body = there may be constant closures inside that need lifting out. *) let _cbody : expression = transl_body env in cexp + | Punboxed_product _ | Punboxed_float | Punboxed_int _ -> begin let cexp = transl env exp in let cbody = transl_body env in @@ -1411,7 +1412,6 @@ and transl_let env str (layout : Lambda.layout) id exp transl_body = end | Pvalue kind -> transl_let_value env str kind id exp transl_body - | Punboxed_product _ -> Misc.fatal_error "TBD" and make_catch (kind : Cmm.kind_for_unboxing) ncatch body handler dbg = match body with diff --git a/middle_end/clambda_primitives.ml b/middle_end/clambda_primitives.ml index 56ba8d23484..ff5dd06b030 100644 --- a/middle_end/clambda_primitives.ml +++ b/middle_end/clambda_primitives.ml @@ -185,4 +185,6 @@ let result_layout (p : primitive) = match p with | Punbox_float -> Lambda.Punboxed_float | Punbox_int bi -> Lambda.Punboxed_int bi + | Pmake_unboxed_product layouts -> Lambda.Punboxed_product layouts + | Punboxed_product_field (field, layouts) -> List.nth layouts field | _ -> Lambda.layout_any_value diff --git a/middle_end/printclambda.ml b/middle_end/printclambda.ml index f69e1c8d257..2e507bac49d 100644 --- a/middle_end/printclambda.ml +++ b/middle_end/printclambda.ml @@ -60,7 +60,10 @@ let layout (layout : Lambda.layout) = | Punboxed_int Pint32 -> ":unboxed_int32" | Punboxed_int Pint64 -> ":unboxed_int64" | Punboxed_int Pnativeint -> ":unboxed_nativeint" - | Punboxed_product _ -> Misc.fatal_error "TODO" + | Punboxed_product layouts -> + Format.asprintf ":unboxed_product(%a)" + (Format.pp_print_list ~pp_sep:(fun ppf () -> Format.fprintf ppf ", ") + Printlambda.layout) layouts let rec structured_constant ppf = function | Uconst_float x -> fprintf ppf "%F" x From 3a631d8c764b522947cf3864b17c4457561b9a6e Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Wed, 5 Apr 2023 21:48:32 +0200 Subject: [PATCH 19/30] Closure fields unarization --- backend/cmm_helpers.ml | 6 ++-- middle_end/flambda/flambda_to_clambda.ml | 41 +++++++++++++----------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/backend/cmm_helpers.ml b/backend/cmm_helpers.ml index 6e19bf909c5..b9febf35699 100644 --- a/backend/cmm_helpers.ml +++ b/backend/cmm_helpers.ml @@ -1060,7 +1060,7 @@ module Extended_machtype = struct let change_tagged_int_to_val t = Array.map Extended_machtype_component.change_tagged_int_to_val t - let of_layout (layout : Lambda.layout) = + let rec of_layout (layout : Lambda.layout) = match layout with | Ptop -> Misc.fatal_error "No Extended_machtype for layout [Ptop]" | Pbottom -> @@ -1071,8 +1071,8 @@ module Extended_machtype = struct typ_any_int | Pvalue Pintval -> typ_tagged_int | Pvalue _ -> typ_val - | Punboxed_product _ -> - Misc.fatal_error "Punboxed_product not expected here" + | Punboxed_product fields -> + Array.concat @@ List.map of_layout fields end let machtype_of_layout layout = diff --git a/middle_end/flambda/flambda_to_clambda.ml b/middle_end/flambda/flambda_to_clambda.ml index a48db8db27a..45dc575b493 100644 --- a/middle_end/flambda/flambda_to_clambda.ml +++ b/middle_end/flambda/flambda_to_clambda.ml @@ -251,15 +251,22 @@ let layout_of_atom (atom : Closure_offsets.layout_atom) : Lambda.layout = | Unboxed_float -> Punboxed_float | Unboxed_int bi -> Punboxed_int bi -let load_var_field ~fun_offset ~check_field (parts : Closure_offsets.parts) : Clambda.ulambda = - match parts with - (* | [] -> failwith "TODO void" *) - | Atom (var_offset, layout) -> - let pos = var_offset - fun_offset in - Uprim (Pfield (pos, layout_of_atom layout), - [check_field pos], - Debuginfo.none) - | _ -> failwith "TODO multiple parts" +let load_env_field ~fun_offset + ~closure_using_field (parts : Closure_offsets.parts) : Clambda.ulambda = + let rec rebuild (parts : Closure_offsets.parts) : Clambda.ulambda * Clambda_primitives.layout = + match parts with + | Atom (var_offset, layout) -> + let pos = var_offset - fun_offset in + let layout = layout_of_atom layout in + Uprim (Pfield (pos, layout), [closure_using_field pos], Debuginfo.none), layout + | Product parts -> + let parts = Array.to_list @@ Array.map rebuild parts in + let parts, layouts = List.split parts in + Uprim (Pmake_unboxed_product layouts, parts, Debuginfo.none), + Punboxed_product layouts + in + let expr, _layout = rebuild parts in + expr let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda * Lambda.layout = match flam with @@ -524,7 +531,8 @@ and to_clambda_named t env var (named : Flambda.named) : Clambda.ulambda * Lambd check_field t (check_closure t ulam (Expr (Var closure))) pos (Some named) in - load_var_field ~fun_offset ~check_field var_offset, kind + load_env_field ~fun_offset ~closure_using_field:check_field var_offset, + kind end | Prim (Pfield (index, layout), [block], dbg) -> begin match layout with @@ -672,14 +680,11 @@ and to_clambda_set_of_closures t env Variable.print id Flambda.print_set_of_closures set_of_closures in - match var_offset with - (* | [] -> failwith "TODO void closure building" *) - | Atom (var_offset, _layout) -> - let pos = var_offset - fun_offset in - Env.add_subst env id - (Uprim (Pfield (pos, spec_to.kind), [Clambda.Uvar env_var], Debuginfo.none)) - spec_to.kind - | _ -> failwith "TODO multiple parts closure building" + let expr = + let closure_using_field _pos = Clambda.Uvar env_var in + load_env_field ~fun_offset ~closure_using_field var_offset + in + Env.add_subst env id expr spec_to.kind in let env = Variable.Map.fold add_env_free_variable free_vars env in (* Add the Clambda expressions for all functions defined in the current From 11af6fc3288bf07a669ce8b1df13c1ab44b2b505 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Tue, 11 Apr 2023 18:48:48 +0200 Subject: [PATCH 20/30] Allocate closures --- middle_end/flambda/flambda_to_clambda.ml | 65 +++++++++++++----------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/middle_end/flambda/flambda_to_clambda.ml b/middle_end/flambda/flambda_to_clambda.ml index 45dc575b493..f0399f80cc1 100644 --- a/middle_end/flambda/flambda_to_clambda.ml +++ b/middle_end/flambda/flambda_to_clambda.ml @@ -268,6 +268,26 @@ let load_env_field ~fun_offset let expr, _layout = rebuild parts in expr +let rec fold_left_layout (f : 'acc -> 'e -> Closure_offsets.layout_atom -> 'acc) + (acc : 'acc) (expr : Clambda.ulambda) (layout : Clambda_primitives.layout) : 'acc = + match layout with + | Ptop -> + Misc.fatal_error "[Ptop] can't be stored in a closure." + | Pbottom -> + Misc.fatal_error + "[Pbottom] should have been eliminated as dead code \ + and not stored in a closure." + | Punboxed_float -> f acc expr Unboxed_float + | Punboxed_int bi -> f acc expr (Unboxed_int bi) + | Pvalue Pintval -> f acc expr Value_int + | Pvalue _ -> f acc expr Value + | Punboxed_product layouts -> + List.fold_left (fun acc (field, layout) -> + let expr : Clambda.ulambda = + Uprim (Punboxed_product_field (field, layouts), [expr], Debuginfo.none) in + fold_left_layout f acc expr layout) acc + (List.mapi (fun i v -> i, v) layouts) + let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda * Lambda.layout = match flam with | Var var -> subst_var env var @@ -729,37 +749,22 @@ and to_clambda_set_of_closures t env in let functions = List.map to_clambda_function all_functions in let not_scanned_fv, scanned_fv = - Variable.Map.partition (fun _ (free_var : Flambda.specialised_to) -> - match free_var.kind with - | Ptop -> Misc.fatal_error "[Ptop] can't be stored in a closure." - | Pbottom -> - Misc.fatal_error - "[Pbottom] should have been eliminated as dead code \ - and not stored in a closure." - | Punboxed_float -> true - | Punboxed_int _ -> true - | Pvalue Pintval -> true - | Pvalue _ -> false - | Punboxed_product _ -> - true - (* Misc.fatal_error "TBD" *) - ) - free_vars - in - let to_closure_args free_vars = - List.map snd ( - Variable.Map.bindings (Variable.Map.map ( - fun (free_var : Flambda.specialised_to) -> - let var, var_layout = subst_var env free_var.var in - assert(Lambda.compatible_layout var_layout free_var.kind); - var - ) free_vars)) + let free_vars = Variable.Map.bindings free_vars in + List.fold_left (fun acc (_var, (free_var : Flambda.specialised_to)) -> + let f (not_scanned_fv, scanned_fv) + (expr: Clambda.ulambda) (atom : Closure_offsets.layout_atom) = + match atom with + | Value -> not_scanned_fv, (expr :: scanned_fv) + | Value_int | Unboxed_float | Unboxed_int _ -> + (expr :: not_scanned_fv, scanned_fv) + in + let closure, var_layout = subst_var env free_var.var in + assert(Lambda.compatible_layout var_layout free_var.kind); + fold_left_layout f acc closure free_var.kind + ) ([],[]) free_vars in - Uclosure { - functions ; - not_scanned_slots = to_closure_args not_scanned_fv ; - scanned_slots = to_closure_args scanned_fv - } + let not_scanned_slots, scanned_slots = List.rev not_scanned_fv, List.rev scanned_fv in + Uclosure { functions; not_scanned_slots; scanned_slots; } and to_clambda_closed_set_of_closures t env symbol ({ function_decls; } : Flambda.set_of_closures) From fdeab843bed035122dcc2e5edc18bfc441780fa9 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Thu, 13 Apr 2023 14:34:23 +0200 Subject: [PATCH 21/30] Test catch --- up.ml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/up.ml b/up.ml index b5753472e86..e14d3162745 100644 --- a/up.ml +++ b/up.ml @@ -289,3 +289,20 @@ external make_unboxed_triple_o_i_o let[@inline never] returns_unboxed_triple_of_void_int_void_not_inlined x = make_unboxed_triple_o_i_o (void ()) x (void ()) + +let[@inline never] ccatch c a b = + let[@local] sub p = + let a = unboxed_pair_field_0_v_v p in + let b = unboxed_pair_field_1_v_v p in + a - b + in + if c then + let p1 = make_unboxed_pair_v_v a b in + sub p1 + else + let p2 = make_unboxed_pair_v_v b a in + sub p2 + +let () = + Printf.printf "%d\n%!" (ccatch true 1 2); + Printf.printf "%d\n%!" (ccatch false 1 2) From 06592dc7aa775f9984c59c7e97e70ab752e762f1 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Thu, 13 Apr 2023 14:36:22 +0200 Subject: [PATCH 22/30] Cleanup --- middle_end/flambda/closure_offsets.ml | 48 --------------------------- 1 file changed, 48 deletions(-) diff --git a/middle_end/flambda/closure_offsets.ml b/middle_end/flambda/closure_offsets.ml index a0e3dbf2654..5c789f19e88 100644 --- a/middle_end/flambda/closure_offsets.ml +++ b/middle_end/flambda/closure_offsets.ml @@ -105,54 +105,6 @@ let assign_invisible_offsets init_pos (var, dec) = let acc, dec = fold_decompose f_visible f_invisible init_pos dec in acc, (var, solidify dec) -(* let rec layout_size (layout : Lambda.layout) = *) -(* match layout with *) -(* | Ptop -> *) -(* Misc.fatal_error "[Ptop] can't be stored in a closure." *) -(* | Pbottom -> *) -(* Misc.fatal_error *) -(* "[Pbottom] should have been eliminated as dead code \ *) -(* and not stored in a closure." *) -(* | Punboxed_float *) -(* | Punboxed_int _ *) -(* | Pvalue Pintval *) -(* | Pvalue _ -> 1 *) -(* | Punboxed_product l -> *) -(* List.fold_left (fun acc e -> acc + layout_size e) 0 l *) -(* let _ = ignore layout_size *) - -(* let split_scannable layout = *) -(* let rec loop (layout : Lambda.layout) path = *) -(* match layout with *) -(* | Ptop -> *) -(* Misc.fatal_error "[Ptop] can't be stored in a closure." *) -(* | Pbottom -> *) -(* Misc.fatal_error *) -(* "[Pbottom] should have been eliminated as dead code \ *) -(* and not stored in a closure." *) -(* | Punboxed_float -> { gc_invisible = [Unboxed_float, path]; gc_visible = [] } *) -(* | Punboxed_int bi -> { gc_invisible = [Unboxed_int bi, path]; gc_visible = [] } *) -(* | Pvalue Pintval -> { gc_invisible = [Value_int, path]; gc_visible = [] } *) -(* | Pvalue _ -> { gc_invisible = []; gc_visible = [Value, path] } *) -(* | Punboxed_product l -> *) -(* let splits = List.mapi (fun i layout -> loop layout (i :: path)) l in *) -(* let merged = *) -(* List.fold_left (fun { gc_invisible; gc_visible } e -> *) -(* { gc_invisible = e.gc_invisible @ gc_invisible; *) -(* gc_visible = e.gc_visible @ gc_visible; }) *) -(* { gc_invisible = []; gc_visible = [] } splits *) -(* in *) -(* (\* match merged.gc_invisible with *\) *) -(* (\* | [] -> { gc_invisible = []; gc_visible = [layout, path] } *\) *) -(* (\* | _ -> *\) *) -(* (\* match merged.gc_visible with *\) *) -(* (\* | [] -> { gc_visible = []; gc_invisible = [layout, path] } *\) *) -(* (\* | _ -> *\) *) -(* merged *) -(* in *) -(* loop layout [] *) - - let add_closure_offsets { function_offsets; free_variable_offsets } ({ function_decls; free_vars } : Flambda.set_of_closures) = From 46f9f15aeb957543d28733411f1466506c415a04 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Thu, 13 Apr 2023 15:05:41 +0200 Subject: [PATCH 23/30] More info in Ctuple_field --- backend/cmm.ml | 2 +- backend/cmm.mli | 2 +- backend/cmmgen.ml | 20 +++++--------------- backend/selectgen.ml | 14 ++++++++++---- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/backend/cmm.ml b/backend/cmm.ml index 6c20cff4c00..2d7c59442c8 100644 --- a/backend/cmm.ml +++ b/backend/cmm.ml @@ -217,7 +217,7 @@ and operation = | Cprobe_is_enabled of { name: string } | Copaque | Cbeginregion | Cendregion - | Ctuple_field of int * machtype + | Ctuple_field of int * machtype array type kind_for_unboxing = | Any diff --git a/backend/cmm.mli b/backend/cmm.mli index cb912ca9f6a..a86ac96663a 100644 --- a/backend/cmm.mli +++ b/backend/cmm.mli @@ -219,7 +219,7 @@ and operation = | Cprobe_is_enabled of { name: string } | Copaque (* Sys.opaque_identity *) | Cbeginregion | Cendregion - | Ctuple_field of int * machtype + | Ctuple_field of int * machtype array (* This is information used exclusively during construction of cmm terms by cmmgen, and thus irrelevant for selectgen and flambda2. *) diff --git a/backend/cmmgen.ml b/backend/cmmgen.ml index d8a97cf1cf2..8b44a6ec2e6 100644 --- a/backend/cmmgen.ml +++ b/backend/cmmgen.ml @@ -618,11 +618,12 @@ let rec transl env e = | arg :: args, layout :: layouts -> let arg = transl env arg in bind "arg" arg (fun arg -> - let layout = flatten_layout layout in + let layout = List.map layout_machtype @@ flatten_layout layout in + let layout_a = Array.of_list layout in let skip = List.length layout in let loads = List.mapi (fun i layout -> - Cop (Ctuple_field (i,(layout_machtype layout)) , [arg], dbg)) + Cop (Ctuple_field (i, layout_a) , [arg], dbg)) layout in loop (offset + skip) args layouts (loads @ acc) @@ -1050,19 +1051,8 @@ and transl_prim_1 env p arg dbg = tag_int (bswap16 (ignore_high_bit_int (untag_int (transl env arg) dbg)) dbg) dbg | Punboxed_product_field (field, layouts) -> - Cmm_helpers.bind "unboxed_product" (transl env arg) (fun arg -> - let prev_layouts = - List.map flatten_layout (take_n field layouts) |> - List.flatten - in - let skip = List.length prev_layouts in - let layout = List.nth layouts field in - let loads = - List.mapi (fun i layout -> - Cop (Ctuple_field (skip + i, layout_machtype layout), [arg], dbg)) - (flatten_layout layout) - in - Ctuple loads) + let layouts = Array.of_list (List.map machtype_of_layout layouts) in + Cop (Ctuple_field (field, layouts), [transl env arg], dbg) | (Pfield_computed | Psequand | Psequor | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint diff --git a/backend/selectgen.ml b/backend/selectgen.ml index 7d7c55a1307..a28fa6c54e6 100644 --- a/backend/selectgen.ml +++ b/backend/selectgen.ml @@ -228,7 +228,7 @@ let oper_result_type = function naked pointer into the local allocation stack. *) typ_int | Cendregion -> typ_void - | Ctuple_field (_, ty) -> ty + | Ctuple_field (field, fields_ty) -> fields_ty.(field) (* Infer the size in bytes of the result of an expression whose evaluation may be deferred (cf. [emit_parts]). *) @@ -920,12 +920,18 @@ method emit_expr_aux (env:environment) exp : let rs = self#emit_tuple env simple_args in ret (self#insert_op_debug env Iopaque dbg rs rs) end - | Cop(Ctuple_field(field, _layout), [arg], dbg) -> + | Cop(Ctuple_field(field, fields_layout), [arg], dbg) -> begin match self#emit_expr env arg with None -> None | Some loc_exp -> - (* All fields are of size one *) - Some [|loc_exp.(field)|] + let flat_size a = Array.fold_left (fun acc t -> acc + Array.length t) 0 a in + assert(Array.length loc_exp = flat_size fields_layout); + let before = Array.sub fields_layout 0 field in + let size_before = flat_size before in + let field_slice = + Array.sub loc_exp size_before (Array.length fields_layout.(field)) + in + Some field_slice end | Cop(op, args, dbg) -> begin match self#emit_parts_list env args with From 18989e06cdcf657c888dbf6ab7c7ad002c1ebb18 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Thu, 13 Apr 2023 16:10:31 +0200 Subject: [PATCH 24/30] Simplify cmmgen --- backend/cmmgen.ml | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/backend/cmmgen.ml b/backend/cmmgen.ml index 8b44a6ec2e6..e6c460e4aaf 100644 --- a/backend/cmmgen.ml +++ b/backend/cmmgen.ml @@ -608,28 +608,8 @@ let rec transl env e = (* Primitives *) | Uprim(prim, args, dbg) -> begin match (simplif_primitive prim, args) with - - | (Pmake_unboxed_product layouts, args) -> - let rec loop offset args layouts acc = - match args, layouts with - | [], [] -> - Ctuple acc - | [], _ | _, [] -> assert false - | arg :: args, layout :: layouts -> - let arg = transl env arg in - bind "arg" arg (fun arg -> - let layout = List.map layout_machtype @@ flatten_layout layout in - let layout_a = Array.of_list layout in - let skip = List.length layout in - let loads = - List.mapi (fun i layout -> - Cop (Ctuple_field (i, layout_a) , [arg], dbg)) - layout - in - loop (offset + skip) args layouts (loads @ acc) - ) - in - loop 0 (List.rev args) (List.rev layouts) [] + | (Pmake_unboxed_product layouts, args) -> + Ctuple (List.map (transl env) args) | (Pread_symbol sym, []) -> Cconst_symbol (global_symbol sym, dbg) | (Pmakeblock _, []) -> From 5936ea5721ae2918aef684c869ec3be3da230b99 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Thu, 13 Apr 2023 17:16:04 +0200 Subject: [PATCH 25/30] Start factorisation with closures --- dune | 2 + middle_end/clambda_layout.ml | 110 +++++++++++++++++++++++ middle_end/clambda_layout.mli | 18 ++++ middle_end/flambda/closure_offsets.ml | 90 ++----------------- middle_end/flambda/closure_offsets.mli | 11 +-- middle_end/flambda/flambda_to_clambda.ml | 24 +---- 6 files changed, 141 insertions(+), 114 deletions(-) create mode 100644 middle_end/clambda_layout.ml create mode 100644 middle_end/clambda_layout.mli diff --git a/dune b/dune index 2eb7a7738a5..73587aa2aed 100755 --- a/dune +++ b/dune @@ -83,6 +83,7 @@ backend_var clambda clambda_primitives + clambda_layout compilenv mangling convert_primitives @@ -532,6 +533,7 @@ (backend_var.mli as compiler-libs/backend_var.mli) (clambda.mli as compiler-libs/clambda.mli) (clambda_primitives.mli as compiler-libs/clambda_primitives.mli) + (clambda_layout.mli as compiler-libs/clambda_layout.mli) (compilenv.mli as compiler-libs/compilenv.mli) (mangling.mli as compiler-libs/mangling.mli) (convert_primitives.mli as compiler-libs/convert_primitives.mli) diff --git a/middle_end/clambda_layout.ml b/middle_end/clambda_layout.ml new file mode 100644 index 00000000000..dd05bbfdbeb --- /dev/null +++ b/middle_end/clambda_layout.ml @@ -0,0 +1,110 @@ +type atom = + | Value + | Value_int + | Unboxed_float + | Unboxed_int of Lambda.boxed_integer + +let rec fold_left_layout (f : 'acc -> 'e -> atom -> 'acc) + (acc : 'acc) (expr : Clambda.ulambda) (layout : Clambda_primitives.layout) : 'acc = + match layout with + | Ptop -> + Misc.fatal_error "[Ptop] can't be stored in a closure." + | Pbottom -> + Misc.fatal_error + "[Pbottom] should have been eliminated as dead code \ + and not stored in a closure." + | Punboxed_float -> f acc expr Unboxed_float + | Punboxed_int bi -> f acc expr (Unboxed_int bi) + | Pvalue Pintval -> f acc expr Value_int + | Pvalue _ -> f acc expr Value + | Punboxed_product layouts -> + List.fold_left (fun acc (field, layout) -> + let expr : Clambda.ulambda = + Uprim (Punboxed_product_field (field, layouts), [expr], Debuginfo.none) in + fold_left_layout f acc expr layout) acc + (List.mapi (fun i v -> i, v) layouts) + +type ('visible, 'invisible) decomposition' = + | Gc_visible of ('visible * atom) + | Gc_invisible of ('invisible * atom) + | Product of ('visible, 'invisible) decomposition' array + +type decomposition = + | Atom of { offset : int; layout : atom } + | Product of decomposition array + +let rec decompose (layout : Lambda.layout) : _ decomposition' = + match layout with + | Ptop -> + Misc.fatal_error "[Ptop] can't be stored in a closure." + | Pbottom -> + Misc.fatal_error + "[Pbottom] should have been eliminated as dead code \ + and not stored in a closure." + | Punboxed_float -> Gc_invisible ((), Unboxed_float) + | Punboxed_int bi -> Gc_invisible ((), Unboxed_int bi) + | Pvalue Pintval -> Gc_invisible ((), Value_int) + | Pvalue _ -> Gc_visible ((), Value) + | Punboxed_product l -> + Product (Array.of_list (List.map decompose l)) + +let rec solidify (dec : (int, int) decomposition') : decomposition = + match dec with + | Gc_visible (offset, layout) -> Atom { offset; layout } + | Gc_invisible (offset, layout) -> Atom { offset; layout } + | Product a -> + Product (Array.map solidify a) + +let rec fold_decompose + (f1 : 'acc -> 'a -> atom -> 'acc * 'b) (f2 : 'acc -> 'c -> atom -> 'acc * 'd) + (acc : 'acc) (d : ('a, 'c) decomposition') : + 'acc * ('b, 'd) decomposition' = + match d with + | Gc_visible (v, layout) -> + let acc, v = f1 acc v layout in + acc, Gc_visible (v, layout) + | Gc_invisible (v, layout) -> + let acc, v = f2 acc v layout in + acc, Gc_invisible (v, layout) + | Product elts -> + let acc, elts = Array.fold_left_map (fold_decompose f1 f2) acc elts in + acc, Product elts + +let atom_size (layout : atom) = + match layout with + | Value + | Value_int + | Unboxed_float + | Unboxed_int _ -> 1 + +let assign_visible_offsets init_pos (var, dec) = + let f_visible acc () layout = + acc + atom_size layout, acc + in + let f_invisible acc () _layout = + acc, () + in + let acc, dec = fold_decompose f_visible f_invisible init_pos dec in + acc, (var, dec) + +let assign_invisible_offsets init_pos (var, dec) = + let f_visible acc off _layout = + acc, off + in + let f_invisible acc () layout = + acc + atom_size layout, acc + in + let acc, dec = fold_decompose f_visible f_invisible init_pos dec in + acc, (var, solidify dec) + +let decompose_free_vars ~base_offset ~free_vars = + let free_vars = + List.map (fun (var, kind) -> var, decompose kind) free_vars + in + let base_offset, free_vars = + List.fold_left_map assign_visible_offsets base_offset free_vars + in + let _base_offset, free_vars = + List.fold_left_map assign_invisible_offsets base_offset free_vars + in + free_vars diff --git a/middle_end/clambda_layout.mli b/middle_end/clambda_layout.mli new file mode 100644 index 00000000000..d145595a6ab --- /dev/null +++ b/middle_end/clambda_layout.mli @@ -0,0 +1,18 @@ +type atom = + | Value + | Value_int + | Unboxed_float + | Unboxed_int of Lambda.boxed_integer + +val fold_left_layout : + ('acc -> Clambda.ulambda -> atom -> 'acc) -> 'acc -> Clambda.ulambda -> + Clambda_primitives.layout -> 'acc + +type decomposition = + | Atom of { offset : int; layout : atom } + | Product of decomposition array + +val decompose_free_vars : + base_offset:int -> + free_vars:('a * Clambda_primitives.layout) list -> + ('a * decomposition) list diff --git a/middle_end/flambda/closure_offsets.ml b/middle_end/flambda/closure_offsets.ml index 5c789f19e88..19e4522ff4c 100644 --- a/middle_end/flambda/closure_offsets.ml +++ b/middle_end/flambda/closure_offsets.ml @@ -16,20 +16,9 @@ [@@@ocaml.warning "+a-4-9-30-40-41-42"] -type layout_atom = - | Value - | Value_int - | Unboxed_float - | Unboxed_int of Lambda.boxed_integer +type layout_atom = Clambda_layout.atom -type ('visible, 'invisible) decomposition' = - | Gc_visible of ('visible * layout_atom) - | Gc_invisible of ('invisible * layout_atom) - | Product of ('visible, 'invisible) decomposition' array - -type decomposition = - | Atom of (int * layout_atom) - | Product of decomposition array +type decomposition = Clambda_layout.decomposition type parts = decomposition let equal_parts (p1 : parts) p2 = p1 = p2 @@ -41,70 +30,6 @@ type result = { free_variable_offsets : parts Var_within_closure.Map.t; } -let rec decompose (layout : Lambda.layout) : _ decomposition' = - match layout with - | Ptop -> - Misc.fatal_error "[Ptop] can't be stored in a closure." - | Pbottom -> - Misc.fatal_error - "[Pbottom] should have been eliminated as dead code \ - and not stored in a closure." - | Punboxed_float -> Gc_invisible ((), Unboxed_float) - | Punboxed_int bi -> Gc_invisible ((), Unboxed_int bi) - | Pvalue Pintval -> Gc_invisible ((), Value_int) - | Pvalue _ -> Gc_visible ((), Value) - | Punboxed_product l -> - Product (Array.of_list (List.map decompose l)) - -let rec solidify (dec : (int, int) decomposition') : decomposition = - match dec with - | Gc_visible (off, layout) -> Atom (off, layout) - | Gc_invisible (off, layout) -> Atom (off, layout) - | Product a -> - Product (Array.map solidify a) - -let rec fold_decompose - (f1 : 'acc -> 'a -> layout_atom -> 'acc * 'b) (f2 : 'acc -> 'c -> layout_atom -> 'acc * 'd) - (acc : 'acc) (d : ('a, 'c) decomposition') : - 'acc * ('b, 'd) decomposition' = - match d with - | Gc_visible (v, layout) -> - let acc, v = f1 acc v layout in - acc, Gc_visible (v, layout) - | Gc_invisible (v, layout) -> - let acc, v = f2 acc v layout in - acc, Gc_invisible (v, layout) - | Product elts -> - let acc, elts = Array.fold_left_map (fold_decompose f1 f2) acc elts in - acc, Product elts - -let layout_atom_size (layout : layout_atom) = - match layout with - | Value - | Value_int - | Unboxed_float - | Unboxed_int _ -> 1 - -let assign_visible_offsets init_pos (var, dec) = - let f_visible acc () layout = - acc + layout_atom_size layout, acc - in - let f_invisible acc () _layout = - acc, () - in - let acc, dec = fold_decompose f_visible f_invisible init_pos dec in - acc, (var, dec) - -let assign_invisible_offsets init_pos (var, dec) = - let f_visible acc off _layout = - acc, off - in - let f_invisible acc () layout = - acc + layout_atom_size layout, acc - in - let acc, dec = fold_decompose f_visible f_invisible init_pos dec in - acc, (var, solidify dec) - let add_closure_offsets { function_offsets; free_variable_offsets } ({ function_decls; free_vars } : Flambda.set_of_closures) = @@ -144,12 +69,11 @@ let add_closure_offsets ideal, and the self accesses should be explicitly marked too. *) let free_vars = Variable.Map.bindings free_vars in let free_vars = List.map (fun (var, (free_var : Flambda.specialised_to)) -> - var, decompose free_var.kind) free_vars in - let free_variable_pos, free_vars = - List.fold_left_map assign_visible_offsets free_variable_pos free_vars - in - let _free_variable_pos, free_vars = - List.fold_left_map assign_invisible_offsets free_variable_pos free_vars + var, free_var.kind) free_vars in + let free_vars = + Clambda_layout.decompose_free_vars + ~base_offset:free_variable_pos + ~free_vars in let free_variable_offsets = List.fold_left (fun map (var, dec) -> diff --git a/middle_end/flambda/closure_offsets.mli b/middle_end/flambda/closure_offsets.mli index a0c7fe94538..858f7ebc59b 100644 --- a/middle_end/flambda/closure_offsets.mli +++ b/middle_end/flambda/closure_offsets.mli @@ -19,16 +19,9 @@ (** Assign numerical offsets, within closure blocks, for code pointers and environment entries. *) -type layout_atom = - | Value - | Value_int - | Unboxed_float - | Unboxed_int of Lambda.boxed_integer +type layout_atom = Clambda_layout.atom -type decomposition = - | Atom of (int * layout_atom) - | Product of decomposition array -type parts = decomposition +type parts = Clambda_layout.decomposition val equal_parts : parts -> parts -> bool val print_parts : Format.formatter -> parts -> unit diff --git a/middle_end/flambda/flambda_to_clambda.ml b/middle_end/flambda/flambda_to_clambda.ml index f0399f80cc1..f26d5435fc0 100644 --- a/middle_end/flambda/flambda_to_clambda.ml +++ b/middle_end/flambda/flambda_to_clambda.ml @@ -255,7 +255,7 @@ let load_env_field ~fun_offset ~closure_using_field (parts : Closure_offsets.parts) : Clambda.ulambda = let rec rebuild (parts : Closure_offsets.parts) : Clambda.ulambda * Clambda_primitives.layout = match parts with - | Atom (var_offset, layout) -> + | Atom { offset = var_offset; layout } -> let pos = var_offset - fun_offset in let layout = layout_of_atom layout in Uprim (Pfield (pos, layout), [closure_using_field pos], Debuginfo.none), layout @@ -268,26 +268,6 @@ let load_env_field ~fun_offset let expr, _layout = rebuild parts in expr -let rec fold_left_layout (f : 'acc -> 'e -> Closure_offsets.layout_atom -> 'acc) - (acc : 'acc) (expr : Clambda.ulambda) (layout : Clambda_primitives.layout) : 'acc = - match layout with - | Ptop -> - Misc.fatal_error "[Ptop] can't be stored in a closure." - | Pbottom -> - Misc.fatal_error - "[Pbottom] should have been eliminated as dead code \ - and not stored in a closure." - | Punboxed_float -> f acc expr Unboxed_float - | Punboxed_int bi -> f acc expr (Unboxed_int bi) - | Pvalue Pintval -> f acc expr Value_int - | Pvalue _ -> f acc expr Value - | Punboxed_product layouts -> - List.fold_left (fun acc (field, layout) -> - let expr : Clambda.ulambda = - Uprim (Punboxed_product_field (field, layouts), [expr], Debuginfo.none) in - fold_left_layout f acc expr layout) acc - (List.mapi (fun i v -> i, v) layouts) - let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda * Lambda.layout = match flam with | Var var -> subst_var env var @@ -760,7 +740,7 @@ and to_clambda_set_of_closures t env in let closure, var_layout = subst_var env free_var.var in assert(Lambda.compatible_layout var_layout free_var.kind); - fold_left_layout f acc closure free_var.kind + Clambda_layout.fold_left_layout f acc closure free_var.kind ) ([],[]) free_vars in let not_scanned_slots, scanned_slots = List.rev not_scanned_fv, List.rev scanned_fv in From 2a72a0140cabf698c3cab746e94b2151d70641d3 Mon Sep 17 00:00:00 2001 From: Pierre Chambart Date: Fri, 14 Apr 2023 11:28:09 +0200 Subject: [PATCH 26/30] Closure done with unboxed product --- middle_end/clambda_layout.ml | 24 +++++----- middle_end/closure/closure.ml | 86 ++++++++++++++++++++++------------- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/middle_end/clambda_layout.ml b/middle_end/clambda_layout.ml index dd05bbfdbeb..d529c844f34 100644 --- a/middle_end/clambda_layout.ml +++ b/middle_end/clambda_layout.ml @@ -77,23 +77,23 @@ let atom_size (layout : atom) = | Unboxed_float | Unboxed_int _ -> 1 -let assign_visible_offsets init_pos (var, dec) = - let f_visible acc () layout = - acc + atom_size layout, acc - in - let f_invisible acc () _layout = +let assign_invisible_offsets init_pos (var, dec) = + let f_visible acc () _layout = acc, () in + let f_invisible acc () layout = + acc + atom_size layout, acc + in let acc, dec = fold_decompose f_visible f_invisible init_pos dec in acc, (var, dec) -let assign_invisible_offsets init_pos (var, dec) = - let f_visible acc off _layout = - acc, off - in - let f_invisible acc () layout = +let assign_visible_offsets init_pos (var, dec) = + let f_visible acc () layout = acc + atom_size layout, acc in + let f_invisible acc off _layout = + acc, off + in let acc, dec = fold_decompose f_visible f_invisible init_pos dec in acc, (var, solidify dec) @@ -102,9 +102,9 @@ let decompose_free_vars ~base_offset ~free_vars = List.map (fun (var, kind) -> var, decompose kind) free_vars in let base_offset, free_vars = - List.fold_left_map assign_visible_offsets base_offset free_vars + List.fold_left_map assign_invisible_offsets base_offset free_vars in let _base_offset, free_vars = - List.fold_left_map assign_invisible_offsets base_offset free_vars + List.fold_left_map assign_visible_offsets base_offset free_vars in free_vars diff --git a/middle_end/closure/closure.ml b/middle_end/closure/closure.ml index 1c2a1e2d26d..37c09fdaa22 100644 --- a/middle_end/closure/closure.ml +++ b/middle_end/closure/closure.ml @@ -50,30 +50,53 @@ let rec split_list n l = | a::l -> let (l1, l2) = split_list (n-1) l in (a::l1, l2) end -let rec add_to_closure_env env_param pos cenv = function - [] -> cenv - | (id, kind) :: rem -> - V.Map.add id - (Uprim(P.Pfield (pos, kind), [Uvar env_param], Debuginfo.none)) - (add_to_closure_env env_param (pos+1) cenv rem) - -let is_gc_ignorable kind = - match kind with - | Ptop -> Misc.fatal_error "[Ptop] can't be stored in a closure." - | Pbottom -> Misc.fatal_error "[Pbottom] should not be stored in a closure." - | Punboxed_float -> true - | Punboxed_int _ -> true - | Pvalue Pintval -> true - | Pvalue (Pgenval | Pfloatval | Pboxedintval _ | Pvariant _ | Parrayval _) -> false - | Punboxed_product _ -> Misc.fatal_error "TBD" - let split_closure_fv kinds fv = - List.fold_right (fun id (not_scanned, scanned) -> - let kind = V.Map.find id kinds in - if is_gc_ignorable kind - then ((id, kind) :: not_scanned, scanned) - else (not_scanned, (id, kind)::scanned)) - fv ([], []) + let (not_scanned_fv, scanned_fv) = + List.fold_left (fun acc id -> + let kind = V.Map.find id kinds in + let f (not_scanned_fv, scanned_fv) expr (atom : Clambda_layout.atom) = + match atom with + | Value -> not_scanned_fv, ((expr, atom) :: scanned_fv) + | Value_int | Unboxed_float | Unboxed_int _ -> + ((expr, atom) :: not_scanned_fv, scanned_fv) + in + Clambda_layout.fold_left_layout f acc (Uvar id) kind) + ([],[]) fv + in + (List.rev not_scanned_fv, List.rev scanned_fv) + +let layout_of_atom (atom : Closure_offsets.layout_atom) : Lambda.layout = + match atom with + | Value -> Pvalue Pgenval + | Value_int -> Pvalue Pintval + | Unboxed_float -> Punboxed_float + | Unboxed_int bi -> Punboxed_int bi + +let load_env_field ~base_offset + ~closure (parts : Clambda_layout.decomposition) : Clambda.ulambda = + let rec rebuild (parts : Closure_offsets.parts) : Clambda.ulambda * Clambda_primitives.layout = + match parts with + | Atom { offset = var_offset; layout } -> + let pos = var_offset + base_offset in + let layout = layout_of_atom layout in + Uprim (Pfield (pos, layout), [closure], Debuginfo.none), layout + | Product parts -> + let parts = Array.to_list @@ Array.map rebuild parts in + let parts, layouts = List.split parts in + Uprim (Pmake_unboxed_product layouts, parts, Debuginfo.none), + Punboxed_product layouts + in + let expr, _layout = rebuild parts in + expr + +let add_to_closure_env env_param base_offset fv = + List.fold_left (fun cenv (id, decomp) -> + let expr = + load_env_field ~base_offset ~closure:(Uvar env_param) + decomp + in + V.Map.add id expr cenv) + V.Map.empty fv (* Auxiliary for accessing globals. We change the name of the global to the name of the corresponding asm symbol. This is done here @@ -1505,7 +1528,7 @@ and close_functions { backend; fenv; cenv; mutable_vars; kinds; catch_env } fun_ let fv = V.Set.elements (free_variables (Lletrec(fun_defs, lambda_unit))) in let not_scanned_fv, scanned_fv = split_closure_fv kinds fv in - let not_scanned_fv_size = List.length not_scanned_fv in + let free_vars = List.map (fun id -> id, V.Map.find id kinds) fv in (* Build the function descriptors for the functions. Initially all functions are assumed not to need their environment parameter. *) @@ -1567,13 +1590,13 @@ and close_functions { backend; fenv; cenv; mutable_vars; kinds; catch_env } fun_ (* Translate each function definition *) let clos_fundef (id, params, return, body, mode, check, fundesc, dbg) env_pos = let env_param = V.create_local "env" in - let cenv_fv = - add_to_closure_env env_param - (fv_pos - env_pos) V.Map.empty not_scanned_fv + let decomposition = + Clambda_layout.decompose_free_vars + ~base_offset:0 + ~free_vars in let cenv_fv = - add_to_closure_env env_param - (fv_pos - env_pos + not_scanned_fv_size) cenv_fv scanned_fv + add_to_closure_env env_param (fv_pos - env_pos) decomposition in let cenv_body = List.fold_right2 @@ -1670,11 +1693,10 @@ and close_functions { backend; fenv; cenv; mutable_vars; kinds; catch_env } fun_ let (clos, infos) = List.split clos_info_list in let not_scanned_fv, scanned_fv = if !useless_env then [], [] else not_scanned_fv, scanned_fv in - let env = { backend; fenv; cenv; mutable_vars; kinds; catch_env } in (Uclosure { functions = clos; - not_scanned_slots = List.map (fun (id, _kind) -> close_var env id) not_scanned_fv; - scanned_slots = List.map (fun (id, _kind) -> close_var env id) scanned_fv + not_scanned_slots = List.map (fun (expr, _kind) -> expr) not_scanned_fv; + scanned_slots = List.map (fun (expr, _kind) -> expr) scanned_fv }, infos) From 1d453df437fe6e7d663a1105c5393088d4c7a5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABlle=20Courant?= Date: Wed, 31 May 2023 16:47:41 +0200 Subject: [PATCH 27/30] fix rebase --- backend/selectgen.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/selectgen.ml b/backend/selectgen.ml index a28fa6c54e6..10e98cb9487 100644 --- a/backend/selectgen.ml +++ b/backend/selectgen.ml @@ -931,7 +931,7 @@ method emit_expr_aux (env:environment) exp : let field_slice = Array.sub loc_exp size_before (Array.length fields_layout.(field)) in - Some field_slice + ret field_slice end | Cop(op, args, dbg) -> begin match self#emit_parts_list env args with From 5018583f5865148f0d2dfe8f424868746c4eafe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABlle=20Courant?= Date: Thu, 1 Jun 2023 12:47:16 +0200 Subject: [PATCH 28/30] fix assert --- ocaml/lambda/lambda.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ocaml/lambda/lambda.ml b/ocaml/lambda/lambda.ml index f98247baccb..6436411cd15 100644 --- a/ocaml/lambda/lambda.ml +++ b/ocaml/lambda/lambda.ml @@ -1424,7 +1424,7 @@ let structured_constant_layout = function | Const_float_array _ | Const_float_block _ -> Pvalue (Parrayval Pfloatarray) let primitive_result_layout (p : primitive) = - assert (Sys.backend_type = Sys.Native); + assert !Clflags.native_code; match p with | Popaque layout | Pobj_magic layout -> layout | Pbytes_to_string | Pbytes_of_string -> layout_string From 0805003e541739c52f086e5a65cc17fc226959bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABlle=20Courant?= Date: Thu, 1 Jun 2023 12:47:46 +0200 Subject: [PATCH 29/30] make fmt --- backend/cmm_helpers.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/cmm_helpers.ml b/backend/cmm_helpers.ml index b9febf35699..f3edcc3f497 100644 --- a/backend/cmm_helpers.ml +++ b/backend/cmm_helpers.ml @@ -1071,8 +1071,7 @@ module Extended_machtype = struct typ_any_int | Pvalue Pintval -> typ_tagged_int | Pvalue _ -> typ_val - | Punboxed_product fields -> - Array.concat @@ List.map of_layout fields + | Punboxed_product fields -> Array.concat @@ List.map of_layout fields end let machtype_of_layout layout = From 10a5f4b487355cdcf681a1137d5ff47698bf6c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABlle=20Courant?= Date: Thu, 1 Jun 2023 12:51:52 +0200 Subject: [PATCH 30/30] fix rebase --- ocaml/typing/predef.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ocaml/typing/predef.ml b/ocaml/typing/predef.ml index b210cf253ad..f5d196c0012 100644 --- a/ocaml/typing/predef.ml +++ b/ocaml/typing/predef.ml @@ -198,10 +198,10 @@ let common_initial_env add_type add_extension empty_env = add_type type_ident decl env and add_type2 type_ident ?(kind=fun _ -> Type_abstract) - ?(layout=Layout.value) + ?(layout=Layout.value ~why:(Primitive type_ident)) ~variance ~separability env = - let param0 = newgenvar Layout.value in - let param1 = newgenvar Layout.value in + let param0 = newgenvar (Layout.value ~why:Type_argument) in + let param1 = newgenvar (Layout.value ~why:Type_argument) in let decl = {type_params = [param0; param1]; type_arity = 2; @@ -222,11 +222,11 @@ let common_initial_env add_type add_extension empty_env = add_type type_ident decl env and add_type3 type_ident ?(kind=fun _ -> Type_abstract) - ?(layout=Layout.value) + ?(layout=Layout.value ~why:(Primitive type_ident)) ~variance ~separability env = - let param0 = newgenvar Layout.value in - let param1 = newgenvar Layout.value in - let param2 = newgenvar Layout.value in + let param0 = newgenvar (Layout.value ~why:Type_argument) in + let param1 = newgenvar (Layout.value ~why:Type_argument) in + let param2 = newgenvar (Layout.value ~why:Type_argument) in let decl = {type_params = [param0; param1; param2]; type_arity = 3;

r4ooKt% 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 F{{Vkw@Ld1^ delta 226192 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