diff options
Diffstat (limited to 'lib/compiler')
| -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 -> |
