aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/compiler/src/beam_ssa.erl18
-rw-r--r--lib/compiler/src/beam_ssa_bsm.erl22
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl26
3 files changed, 52 insertions, 14 deletions
diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl
index a71802cf80..c5e23d2ae0 100644
--- a/lib/compiler/src/beam_ssa.erl
+++ b/lib/compiler/src/beam_ssa.erl
@@ -579,11 +579,11 @@ used(_) -> [].
-spec definitions(Blocks :: block_map()) -> definition_map().
definitions(Blocks) ->
- beam_ssa:fold_instrs_rpo(fun(#b_set{ dst = Var }=I, Acc) ->
- maps:put(Var, I, Acc);
- (_Terminator, Acc) ->
- Acc
- end, [0], #{}, Blocks).
+ fold_instrs_rpo(fun(#b_set{ dst = Var }=I, Acc) ->
+ maps:put(Var, I, Acc);
+ (_Terminator, Acc) ->
+ Acc
+ end, [0], #{}, Blocks).
-spec uses(Blocks :: block_map()) -> usage_map().
uses(Blocks) ->
@@ -593,7 +593,7 @@ uses(Blocks) ->
From :: [label()],
Blocks :: block_map().
uses(From, Blocks) ->
- beam_ssa:fold_rpo(fun fold_uses_block/3, From, #{}, Blocks).
+ fold_rpo(fun fold_uses_block/3, From, #{}, Blocks).
fold_uses_block(Lbl, #b_blk{is=Is,last=Last}, UseMap0) ->
F = fun(I, UseMap) ->
@@ -601,7 +601,7 @@ fold_uses_block(Lbl, #b_blk{is=Is,last=Last}, UseMap0) ->
Uses0 = maps:get(Var, Acc, []),
Uses = [{Lbl, I} | Uses0],
maps:put(Var, Uses, Acc)
- end, UseMap, beam_ssa:used(I))
+ end, UseMap, used(I))
end,
F(Last, foldl(F, UseMap0, Is)).
@@ -798,8 +798,8 @@ split_blocks_1([L|Ls], P, Blocks0, Count0) ->
BefBlk = Blk#b_blk{is=Bef,last=Br},
NewBlk = Blk#b_blk{is=Aft},
Blocks1 = Blocks0#{L:=BefBlk,NewLbl=>NewBlk},
- Successors = beam_ssa:successors(NewBlk),
- Blocks = beam_ssa:update_phi_labels(Successors, L, NewLbl, Blocks1),
+ Successors = successors(NewBlk),
+ Blocks = update_phi_labels(Successors, L, NewLbl, Blocks1),
split_blocks_1([NewLbl|Ls], P, Blocks, Count);
no ->
split_blocks_1(Ls, P, Blocks0, Count0)
diff --git a/lib/compiler/src/beam_ssa_bsm.erl b/lib/compiler/src/beam_ssa_bsm.erl
index 2efeb6b5b6..9631bf3334 100644
--- a/lib/compiler/src/beam_ssa_bsm.erl
+++ b/lib/compiler/src/beam_ssa_bsm.erl
@@ -354,6 +354,11 @@ amb_get_alias(#b_var{}=Arg, Lbl, State) ->
error ->
{Arg, State}
end;
+amb_get_alias(#b_remote{mod=Mod0,name=Name0}=Arg0, Lbl, State0) ->
+ {Mod, State1} = amb_get_alias(Mod0, Lbl, State0),
+ {Name, State} = amb_get_alias(Name0, Lbl, State1),
+ Arg = Arg0#b_remote{mod=Mod,name=Name},
+ {Arg, State};
amb_get_alias(Arg, _Lbl, State) ->
{Arg, State}.
@@ -391,15 +396,22 @@ amb_insert_promotions(Blocks0, State) ->
Block = maps:get(Lbl, Blocks),
Alias = Promotion#b_set.dst,
- {Before, After} = splitwith(fun(#b_set{args=Args}) ->
- not member(Alias, Args)
- end, Block#b_blk.is),
+ {Before, After} = splitwith(
+ fun(#b_set{args=Args}) ->
+ not is_var_in_args(Alias, Args)
+ end, Block#b_blk.is),
Is = Before ++ [Promotion | After],
maps:put(Lbl, Block#b_blk{is=Is}, Blocks)
end,
maps:fold(F, Blocks0, State#amb.promotions).
+is_var_in_args(Var, [Var | _]) -> true;
+is_var_in_args(Var, [#b_remote{name=Var} | _]) -> true;
+is_var_in_args(Var, [#b_remote{mod=Var} | _]) -> true;
+is_var_in_args(Var, [_ | Args]) -> is_var_in_args(Var, Args);
+is_var_in_args(_Var, []) -> false.
+
%%%
%%% Subpasses
%%%
@@ -732,6 +744,10 @@ aca_cs_args([Arg | Args], VRs) ->
aca_cs_args([], _VRs) ->
[].
+aca_cs_arg(#b_remote{mod=Mod0,name=Name0}=Rem, VRs) ->
+ Mod = aca_cs_arg(Mod0, VRs),
+ Name = aca_cs_arg(Name0, VRs),
+ Rem#b_remote{mod=Mod,name=Name};
aca_cs_arg(Arg, VRs) ->
case VRs of
#{ Arg := New } -> New;
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index f021177c61..8e105c6244 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -42,7 +42,8 @@
parse_xml/1,get_payload/1,escape/1,num_slots_different/1,
beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1,
expression_before_match/1,erl_689/1,restore_on_call/1,
- restore_after_catch/1,matches_on_parameter/1,big_positions/1]).
+ restore_after_catch/1,matches_on_parameter/1,big_positions/1,
+ matching_meets_apply/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -76,7 +77,8 @@ groups() ->
get_payload,escape,num_slots_different,
beam_bsm,guard,is_ascii,non_opt_eq,
expression_before_match,erl_689,restore_on_call,
- matches_on_parameter,big_positions]}].
+ matches_on_parameter,big_positions,
+ matching_meets_apply]}].
init_per_suite(Config) ->
@@ -1889,4 +1891,24 @@ bp_getpos(<<_:((1 bsl 27) - 8),T/bits>>) -> bp_getpos(T);
bp_getpos(<<A,1:1,"gurka",A>>) -> {a,A};
bp_getpos(<<B,"hello",B>>) -> {b,B}.
+matching_meets_apply(_Config) ->
+ <<"abc">> = do_matching_meets_apply(<<"/abc">>, []),
+ 42 = do_matching_meets_apply(<<"">>, {erlang,-42}),
+ 100 = do_matching_meets_apply(no_binary, {erlang,-100}),
+ ok.
+
+do_matching_meets_apply(<<$/, Rest/binary>>, _Handler) ->
+ id(Rest);
+do_matching_meets_apply(<<_/binary>>=Name, never_matches_a) ->
+ %% Used to crash the compiler because variables in a remote
+ %% were not handled properly by beam_ssa_bsm.
+ Name:foo(gurka);
+do_matching_meets_apply(<<_/binary>>=Name, never_matches_b) ->
+ %% Another case of the above.
+ foo:Name(gurka);
+do_matching_meets_apply(_Bin, {Handler, State}) ->
+ %% Another case of the above.
+ Handler:abs(State).
+
+
id(I) -> I.