From 479eaa7cf2eb0701af7aeb4a94da5cd13ec7de67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 15 Aug 2019 06:38:38 +0200 Subject: Fix an internal consistency check failure caused by beam_except https://bugs.erlang.org/browse/ERL-1026 --- lib/compiler/src/beam_except.erl | 32 ++++++++++++++++++++------------ lib/compiler/test/beam_except_SUITE.erl | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl index 2305502800..2b9c1b0cf5 100644 --- a/lib/compiler/src/beam_except.erl +++ b/lib/compiler/src/beam_except.erl @@ -152,7 +152,7 @@ dig_out_fc(Arity, Is0) -> ({test,_,_,_}) -> false; (_) -> true end, Is0), - {Regs,Acc} = dig_out_fc_1(reverse(Is), Regs0, Acc0), + {Regs,Acc} = dig_out_fc_1(reverse(Is), Arity, Regs0, Acc0), case Regs of #{{x,0}:={atom,function_clause},{x,1}:=Args} -> case moves_from_stack(Args, 0, []) of @@ -165,19 +165,27 @@ dig_out_fc(Arity, Is0) -> no end. -dig_out_fc_1([{block,Bl}|Is], Regs0, Acc) -> +dig_out_fc_1([{block,Bl}|Is], Arity, Regs0, Acc) -> Regs = dig_out_fc_block(Bl, Regs0), - dig_out_fc_1(Is, Regs, Acc); -dig_out_fc_1([{bs_set_position,_,_}=I|Is], Regs, Acc) -> - dig_out_fc_1(Is, Regs, [I|Acc]); -dig_out_fc_1([{bs_get_tail,Src,Dst,Live0}|Is], Regs0, Acc) -> - Regs = prune_xregs(Live0, Regs0), - Live = dig_out_stack_live(Regs, Live0), - I = {bs_get_tail,Src,Dst,Live}, - dig_out_fc_1(Is, Regs, [I|Acc]); -dig_out_fc_1([_|_], _Regs, _Acc) -> + dig_out_fc_1(Is, Arity, Regs, Acc); +dig_out_fc_1([{bs_set_position,_,_}=I|Is], Arity, Regs, Acc) -> + dig_out_fc_1(Is, Arity, Regs, [I|Acc]); +dig_out_fc_1([{bs_get_tail,Src,Dst,Live0}|Is], Arity, Regs0, Acc) -> + case Src of + {x,X} when X < Arity -> + %% The heuristic for determining the number of live + %% registers is likely to give an incorrect result. + %% Give up. + {#{},[]}; + _ -> + Regs = prune_xregs(Live0, Regs0), + Live = dig_out_stack_live(Regs, Live0), + I = {bs_get_tail,Src,Dst,Live}, + dig_out_fc_1(Is, Arity, Regs, [I|Acc]) + end; +dig_out_fc_1([_|_], _Arity, _Regs, _Acc) -> {#{},[]}; -dig_out_fc_1([], Regs, Acc) -> +dig_out_fc_1([], _Arity, Regs, Acc) -> {Regs,Acc}. dig_out_fc_block([{set,[],[],{alloc,Live,_}}|Is], Regs0) -> diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl index 67947dc292..f52239f2a8 100644 --- a/lib/compiler/test/beam_except_SUITE.erl +++ b/lib/compiler/test/beam_except_SUITE.erl @@ -72,11 +72,25 @@ bs_get_tail(Config) -> {function_clause, [{?MODULE,bs_get_tail_1,[<<>>,0,0,Config],_}|_]}} = (catch bs_get_tail_1(id(<<>>), 0, 0, Config)), + + ok = bs_get_tail_2(<<"W">>, <<"X">>, <<"Z">>), + ok = bs_get_tail_2(<<"M">>, <<"X">>, <<"Z">>), + {'EXIT', + {function_clause, + [{?MODULE,do_get_bs_tail_2,[<<"A">>,<<"B">>,[],<<"C">>],_}|_]}} = + (catch bs_get_tail_2(<<"A">>, <<"B">>, <<"C">>)), + ok. bs_get_tail_1(<<_:32, Rest/binary>>, Z1, Z2, F1) -> {Rest,Z1,Z2,F1}. +bs_get_tail_2(A, B, C) -> + do_get_bs_tail_2(A, B, [], C). + +do_get_bs_tail_2(<<"W">>, <<"X">>, _, <<"Z">>) -> ok; +do_get_bs_tail_2(<<"M">>, <<"X">>, _, <<"Z">>) -> ok. + coverage(_) -> File = {file,"fake.erl"}, ok = fc(a), -- cgit v1.2.3