diff options
-rw-r--r-- | lib/compiler/src/beam_ssa.erl | 18 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_bsm.erl | 22 | ||||
-rw-r--r-- | lib/compiler/test/bs_match_SUITE.erl | 26 |
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. |