diff options
| author | Frej Drejhammar <frej.drejhammar@gmail.com> | 2023-03-10 08:34:59 +0100 |
|---|---|---|
| committer | Frej Drejhammar <frej.drejhammar@gmail.com> | 2023-03-10 09:54:05 +0100 |
| commit | 0bac830c937c7c39b6aae37a73bd135841dde969 (patch) | |
| tree | 1ad21e5496b2425ebc7f37ad7f9f931dac25aaa0 | |
| parent | 8130d7ff72b9a7344bbf38ae11283eb01aab3ae5 (diff) | |
| download | erlang-0bac830c937c7c39b6aae37a73bd135841dde969.tar.gz | |
compiler: Be stricter when tracking values in private append
Tracking values to patch into writable binaries in the private append
pass doesn't make any attempt to use type information to exclude
execution paths not relevant when tracking an appendable binary. In
order to avoid later failed attempts to rewrite non-bitstring literals
into bs_init_writable-created values during the rewrite phase, we
change the tracking phase to preemptively abort tracking as soon as we
detect that the element we are tracking can't apply to the literal.
Closes #6999
| -rw-r--r-- | lib/compiler/src/beam_ssa_private_append.erl | 32 | ||||
| -rw-r--r-- | lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl | 13 |
2 files changed, 36 insertions, 9 deletions
diff --git a/lib/compiler/src/beam_ssa_private_append.erl b/lib/compiler/src/beam_ssa_private_append.erl index aab7d73936..bb68dc12f9 100644 --- a/lib/compiler/src/beam_ssa_private_append.erl +++ b/lib/compiler/src/beam_ssa_private_append.erl @@ -167,16 +167,30 @@ get_results(SSA, Element, Fun, DefSt) -> get_results([{_,#b_blk{last=#b_ret{arg=#b_var{}=V}}}|Rest], Acc, Element, Fun, DefSt) -> get_results(Rest, [{V,Element}|Acc], Element, Fun, DefSt); -get_results([{_,#b_blk{last=#b_ret{arg=#b_literal{val=Lit}}}}|Rest], - Acc, Element=self, Fun, DefSt) when not is_bitstring(Lit) -> - %% As value tracking is done without type information, we can - %% follow def chains which don't terminate in a bitstring. This is - %% harmless, but we should ignore them and not, later on, try to - %% patch them to a bs_writable_binary. - get_results(Rest, Acc, Element, Fun, DefSt); -get_results([{Lbl,#b_blk{last=#b_ret{arg=#b_literal{}}}}|Rest], +get_results([{Lbl,#b_blk{last=#b_ret{arg=#b_literal{val=Lit}}}}|Rest], Acc, Element, Fun, DefSt0) -> - DefSt = add_literal(Fun, {ret,Lbl,Element}, DefSt0), + %% As tracking doesn't make any attempt to use type information to + %% exclude execution paths not relevant when tracking an + %% appendable binary, it can happen that we encounter literals + %% which do not match the type of the element. We can safely stop + %% the tracking in that case. + Continue = case Element of + {tuple_elements,_} -> + is_tuple(Lit); + {tuple_element,_,_} -> + is_tuple(Lit); + Elements when is_list(Elements) -> + is_tuple(Lit); + self -> + is_bitstring(Lit); + {hd,_} -> + is_list(Lit) andalso (Lit =/= []) + end, + DefSt = if Continue -> + add_literal(Fun, {ret,Lbl,Element}, DefSt0); + true -> + DefSt0 + end, get_results(Rest, Acc, Element, Fun, DefSt); get_results([_|Rest], Acc, Element, Fun, DefSt) -> get_results(Rest, Acc, Element, Fun, DefSt); diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl index 508bc90c81..881cbeccee 100644 --- a/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl +++ b/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl @@ -58,6 +58,7 @@ transformable31b/1, transformable32/0, transformable32/1, + transformable33/0, not_transformable1/2, not_transformable2/1, @@ -749,6 +750,18 @@ transformable32(#{}) -> transformable32(_) -> <<>>. +%% Check that we don't crash (Github issue #6999) while attempting to +%% patch the empty list, but also that Dest is created with private_append. +transformable33() -> +%ssa% () when post_ssa_opt -> +%ssa% _ = bs_create_bin(private_append, ...). + [F01] = [transformable33_inner(<<"0">>) || _ <- [1]], + Dest = <<F01/binary>>, + Dest. + +transformable33_inner(V) -> + << <<C>> || <<C:4>> <= V >>. + % Should not be transformed as we can't know the alias status of Acc not_transformable1([H|T], Acc) -> %ssa% (_, Arg1) when post_ssa_opt -> |
