summaryrefslogtreecommitdiff
path: root/lib/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/beam_ssa_private_append.erl32
-rw-r--r--lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl13
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 ->