diff options
Diffstat (limited to 'lib/compiler/src')
| -rw-r--r-- | lib/compiler/src/Makefile | 1 | ||||
| -rw-r--r-- | lib/compiler/src/beam_except.erl | 244 | ||||
| -rw-r--r-- | lib/compiler/src/beam_ssa.erl | 2 | ||||
| -rw-r--r-- | lib/compiler/src/beam_ssa_codegen.erl | 74 | ||||
| -rw-r--r-- | lib/compiler/src/beam_ssa_pre_codegen.erl | 116 | ||||
| -rw-r--r-- | lib/compiler/src/compile.erl | 3 | ||||
| -rw-r--r-- | lib/compiler/src/compiler.app.src | 1 | 
7 files changed, 184 insertions, 257 deletions
| diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index 87b0d345f2..0c1dc30f9c 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -52,7 +52,6 @@ MODULES =  \  	beam_clean \  	beam_dict \  	beam_disasm \ -	beam_except \  	beam_flatten \  	beam_jump \  	beam_listing \ diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl deleted file mode 100644 index 28c89782c9..0000000000 --- a/lib/compiler/src/beam_except.erl +++ /dev/null @@ -1,244 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2011-2018. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%%     http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(beam_except). --export([module/2]). - -%%% Rewrite certain calls to erlang:error/{1,2} to specialized -%%% instructions: -%%% -%%% erlang:error({badmatch,Value})       => badmatch Value -%%% erlang:error({case_clause,Value})    => case_end Value -%%% erlang:error({try_clause,Value})     => try_case_end Value -%%% erlang:error(if_clause)              => if_end -%%% erlang:error(function_clause, Args)  => jump FuncInfoLabel -%%% - --import(lists, [reverse/1,reverse/2,seq/2,splitwith/2]). - --spec module(beam_utils:module_code(), [compile:option()]) -> -                    {'ok',beam_utils:module_code()}. - -module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> -    Fs = [function(F) || F <- Fs0], -    {ok,{Mod,Exp,Attr,Fs,Lc}}. - -function({function,Name,Arity,CLabel,Is0}) -> -    try -	Is = function_1(Is0), -	{function,Name,Arity,CLabel,Is} -    catch -        Class:Error:Stack -> -	    io:fwrite("Function: ~w/~w\n", [Name,Arity]), -	    erlang:raise(Class, Error, Stack) -    end. - --record(st, -	{lbl :: beam_asm:label(),              %func_info label -	 loc :: [_],                           %location for func_info -	 arity :: arity()                      %arity for function -	 }). - -function_1(Is0) -> -    case Is0 of -	[{label,Lbl},{line,Loc},{func_info,_,_,Arity}|_] -> -	    St = #st{lbl=Lbl,loc=Loc,arity=Arity}, -	    translate(Is0, St, []); -	[{label,_}|_] -> -	    %% No line numbers. The source must be a .S file. -	    %% There is no need to do anything. -	    Is0 -    end. - -translate([{call_ext,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) -> -    translate_1(Ar, I, Is, St, Acc); -translate([I|Is], St, Acc) -> -    translate(Is, St, [I|Acc]); -translate([], _, Acc) -> -    reverse(Acc). - -translate_1(Ar, I, Is, #st{arity=Arity}=St, [{line,_}=Line|Acc1]=Acc0) -> -    case dig_out(Ar, Arity, Acc1) of -	no -> -	    translate(Is, St, [I|Acc0]); -	{yes,function_clause,Acc2} -> -	    case {Is,Line,St} of -		{[return|_],{line,Loc},#st{lbl=Fi,loc=Loc}} -> -		    Instr = {jump,{f,Fi}}, -		    translate(Is, St, [Instr|Acc2]); -		{_,_,_} -> -                    %% Not a call_only instruction, or not the same -                    %% location information as in in the line instruction -                    %% before the func_info instruction. Not safe -                    %% to translate to a jump. -		    translate(Is, St, [I|Acc0]) -	    end; -	{yes,Instr,Acc2} -> -	    translate(Is, St, [Instr,Line|Acc2]) -    end. - -dig_out(1, _Arity, Is) -> -    dig_out(Is); -dig_out(2, Arity, Is) -> -    dig_out_fc(Arity, Is); -dig_out(_, _, _) -> no. - -dig_out([{block,Bl0}|Is]) -> -    case dig_out_block(reverse(Bl0)) of -	no -> no; -	{yes,What,[]} -> -	    {yes,What,Is}; -	{yes,What,Bl} -> -	    {yes,What,[{block,Bl}|Is]} -    end; -dig_out(_) -> no. - -dig_out_block([{set,[{x,0}],[{atom,if_clause}],move}]) -> -    {yes,if_end,[]}; -dig_out_block([{set,[{x,0}],[{literal,{Exc,Value}}],move}|Is]) -> -    translate_exception(Exc, {literal,Value}, Is, 0); -dig_out_block([{set,[{x,0}],[{atom,Exc},Value],put_tuple2}|Is]) -> -    translate_exception(Exc, Value, Is, 3); -dig_out_block(_) -> no. - -translate_exception(badmatch, Val, Is, Words) -> -    {yes,{badmatch,Val},fix_block(Is, Words)}; -translate_exception(case_clause, Val, Is, Words) -> -    {yes,{case_end,Val},fix_block(Is, Words)}; -translate_exception(try_clause, Val, Is, Words) -> -    {yes,{try_case_end,Val},fix_block(Is, Words)}; -translate_exception(_, _, _, _) -> no. - -fix_block(Is, 0) -> -    reverse(Is); -fix_block(Is, Words) -> -    reverse(fix_block_1(Is, Words)). - -fix_block_1([{set,[],[],{alloc,Live,{F1,F2,Needed0,F3}}}|Is], Words) -> -    case Needed0 - Words of -        0 -> -            Is; -        Needed -> -            true = Needed >= 0,				%Assertion. -            [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is] -    end; -fix_block_1([I|Is], Words) -> -    [I|fix_block_1(Is, Words)]. - - -dig_out_fc(Arity, Is0) -> -    Regs0 = maps:from_list([{{x,X},{arg,X}} || X <- seq(0, Arity-1)]), -    {Is,Acc0} = splitwith(fun({label,_}) -> false; -                             ({test,_,_,_}) -> false; -                             (_) -> true -                          end, Is0), -    {Regs,Acc} = dig_out_fc_1(reverse(Is), Regs0, Acc0), -    case Regs of -        #{{x,0}:={atom,function_clause},{x,1}:=Args} -> -            case moves_from_stack(Args, 0, []) of -                {Moves,Arity} -> -                    {yes,function_clause,reverse(Moves, Acc)}; -                {_,_} -> -                    no -            end; -        #{} -> -            no -    end. - -dig_out_fc_1([{block,Bl}|Is], 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([], Regs, Acc) -> -    {Regs,Acc}. - -dig_out_fc_block([{set,[],[],{alloc,Live,_}}|Is], Regs0) -> -    Regs = prune_xregs(Live, Regs0), -    dig_out_fc_block(Is, Regs); -dig_out_fc_block([{set,[Dst],[Hd,Tl],put_list}|Is], Regs0) -> -    Regs = Regs0#{Dst=>{cons,get_reg(Hd, Regs0),get_reg(Tl, Regs0)}}, -    dig_out_fc_block(Is, Regs); -dig_out_fc_block([{set,[Dst],[Src],move}|Is], Regs0) -> -    Regs = Regs0#{Dst=>get_reg(Src, Regs0)}, -    dig_out_fc_block(Is, Regs); -dig_out_fc_block([{set,_,_,_}|_], _Regs) -> -    %% Unknown instruction. Fail. -    #{}; -dig_out_fc_block([], Regs) -> Regs. - -dig_out_stack_live(Regs, Default) -> -    Reg = {x,2}, -    case Regs of -        #{Reg:=List} -> -            dig_out_stack_live_1(List, Default); -        #{} -> -            Default -    end. - -dig_out_stack_live_1({cons,{arg,N},T}, Live) -> -    dig_out_stack_live_1(T, max(N + 1, Live)); -dig_out_stack_live_1({cons,_,T}, Live) -> -    dig_out_stack_live_1(T, Live); -dig_out_stack_live_1(nil, Live) -> -    Live; -dig_out_stack_live_1(_, Live) -> Live. - -prune_xregs(Live, Regs) -> -    maps:filter(fun({x,X}, _) -> X < Live end, Regs). - -moves_from_stack({cons,{arg,N},_}, I, _Acc) when N =/= I -> -    %% Wrong argument. Give up. -    {[],-1}; -moves_from_stack({cons,H,T}, I, Acc) -> -    case H of -        {arg,I} -> -            moves_from_stack(T, I+1, Acc); -        _ -> -            moves_from_stack(T, I+1, [{move,H,{x,I}}|Acc]) -    end; -moves_from_stack(nil, I, Acc) -> -    {reverse(Acc),I}; -moves_from_stack({literal,[H|T]}, I, Acc) -> -    Cons = {cons,tag_literal(H),tag_literal(T)}, -    moves_from_stack(Cons, I, Acc); -moves_from_stack(_, _, _) -> -    %% Not understood. Give up. -    {[],-1}. - - -get_reg(R, Regs) -> -    case Regs of -        #{R:=Val} -> Val; -        #{} -> R -    end. - -tag_literal([]) -> nil; -tag_literal(T) when is_atom(T) -> {atom,T}; -tag_literal(T) when is_float(T) -> {float,T}; -tag_literal(T) when is_integer(T) -> {integer,T}; -tag_literal(T) -> {literal,T}. diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl index a9977b0b1d..e8b77e382f 100644 --- a/lib/compiler/src/beam_ssa.erl +++ b/lib/compiler/src/beam_ssa.erl @@ -118,7 +118,7 @@  %% Primops only used internally during code generation.  -type cg_prim_op() :: 'bs_get' | 'bs_match_string' | 'bs_restore' | 'bs_skip' | -                      'copy' | 'put_tuple_arity' | 'put_tuple_element' | +                      'copy' | 'match_fail' | 'put_tuple_arity' | 'put_tuple_element' |                        'set_tuple_element'.  -import(lists, [foldl/3,keyfind/3,mapfoldl/3,member/2,reverse/1]). diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl index c2d5035b19..5ce44c97db 100644 --- a/lib/compiler/src/beam_ssa_codegen.erl +++ b/lib/compiler/src/beam_ssa_codegen.erl @@ -37,7 +37,8 @@               used_labels=gb_sets:empty() :: gb_sets:set(ssa_label()),               regs=#{} :: #{beam_ssa:var_name()=>ssa_register()},               ultimate_fail=1 :: beam_label(), -             catches=gb_sets:empty() :: gb_sets:set(ssa_label()) +             catches=gb_sets:empty() :: gb_sets:set(ssa_label()), +             fc_label=1 :: beam_label()               }).  -spec module(beam_ssa:b_module(), [compile:option()]) -> @@ -124,7 +125,7 @@ function(#b_function{anno=Anno,bs=Blocks}, AtomMod, St0) ->          Labels = (St4#cg.labels)#{0=>Entry,?BADARG_BLOCK=>0},          St5 = St4#cg{labels=Labels,used_labels=gb_sets:singleton(Entry),                       ultimate_fail=Ult}, -        {Body,St} = cg_fun(Blocks, St5), +        {Body,St} = cg_fun(Blocks, St5#cg{fc_label=Fi}),          Asm = [{label,Fi},line(Anno),                 {func_info,AtomMod,{atom,Name},Arity}] ++                 add_parameter_annos(Body, Anno) ++ @@ -384,6 +385,7 @@ classify_heap_need(is_tagged_tuple) -> neutral;  classify_heap_need(kill_try_tag) -> gc;  classify_heap_need(landingpad) -> gc;  classify_heap_need(make_fun) -> gc; +classify_heap_need(match_fail) -> gc;  classify_heap_need(new_try_tag) -> gc;  classify_heap_need(peek_message) -> gc;  classify_heap_need(put_map) -> gc; @@ -1160,6 +1162,10 @@ cg_block([#cg_set{op=call}=I,            #cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) ->      %% A call in try/catch block.      cg_block([I], none, St); +cg_block([#cg_set{op=match_fail}=I, +          #cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) -> +    %% A match_fail instruction in a try/catch block. +    cg_block([I], none, St);  cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=I,            #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->      [Dst|Args] = beam_args([Dst0|Args0], St), @@ -1216,6 +1222,28 @@ cg_block([#cg_set{op=copy}|_]=T0, Context, St0) ->          no ->              {Is,St}      end; +cg_block([#cg_set{op=match_fail,args=Args0,anno=Anno}], none, St) -> +    Args = beam_args(Args0, St), +    Is = cg_match_fail(Args, line(Anno), none), +    {Is,St}; +cg_block([#cg_set{op=match_fail,args=Args0,anno=Anno}|T], Context, St0) -> +    FcLabel = case Context of +                  {return,_,none} -> +                      %% There is no stack frame. If this is a function_clause +                      %% exception, it is safe to jump to the label of the +                      %% func_info instruction. +                      St0#cg.fc_label; +                  _ -> +                      %% This is most probably not a function_clause. +                      %% If this is a function_clause exception +                      %% (rare), it is not safe to jump to the +                      %% func_info label. +                      none +              end, +    Args = beam_args(Args0, St0), +    Is0 = cg_match_fail(Args, line(Anno), FcLabel), +    {Is1,St} = cg_block(T, Context, St0), +    {Is0++Is1,St};  cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=Set], none, St) ->      [Dst|Args] = beam_args([Dst0|Args0], St),      Is = cg_instr(Op, Args, Dst, Set), @@ -1489,6 +1517,42 @@ cg_call(#cg_set{anno=Anno,op=call,dst=Dst0,args=Args0},      Is = setup_args(Args++[Func], Anno, Context, St) ++ Line ++ Call,      {Is,St}. +cg_match_fail([{atom,function_clause}|Args], Line, Fc) -> +    case Fc of +        none -> +            %% There is a stack frame (probably because of inlining). +            %% Jumping to the func_info label is not allowed by +            %% beam_validator. Rewrite the instruction as a call to +            %% erlang:error/2. +            make_fc(Args, Line); +        _ -> +            setup_args(Args) ++ [{jump,{f,Fc}}] +    end; +cg_match_fail([{atom,Op}], Line, _Fc) -> +    [Line,Op]; +cg_match_fail([{atom,Op},Val], Line, _Fc) -> +    [Line,{Op,Val}]. + +make_fc(Args, Line) -> +    %% Recreate the original call to erlang:error/2. +    Live = foldl(fun({x,X}, A) -> max(X+1, A); +                    (_, A) -> A +                 end, 0, Args), +    TmpReg = {x,Live}, +    StkMoves = build_stk(reverse(Args), TmpReg, nil), +    [{test_heap,2*length(Args),Live}|StkMoves] ++ +        [{move,{atom,function_clause},{x,0}}, +         Line, +         {call_ext,2,{extfunc,erlang,error,2}}]. + +build_stk([V], _TmpReg, Tail) -> +    [{put_list,V,Tail,{x,1}}]; +build_stk([V|Vs], TmpReg, Tail) -> +    I = {put_list,V,Tail,TmpReg}, +    [I|build_stk(Vs, TmpReg, TmpReg)]; +build_stk([], _TmpReg, nil) -> +    [{move,nil,{x,1}}]. +  build_call(call_fun, Arity, _Func, none, Dst) ->      [{call_fun,Arity}|copy({x,0}, Dst)];  build_call(call_fun, Arity, _Func, {return,Dst,N}, Dst) when is_integer(N) -> @@ -1527,15 +1591,15 @@ build_apply(Arity, {return,Val,N}, _Dst) when is_integer(N) ->  build_apply(Arity, none, Dst) ->      [{apply,Arity}|copy({x,0}, Dst)]. -cg_instr(put_map, [{atom,assoc},SrcMap|Ss], Dst, Set) -> -    Live = get_live(Set), -    [{put_map_assoc,{f,0},SrcMap,Dst,Live,{list,Ss}}];  cg_instr(bs_get_tail, [Src], Dst, Set) ->      Live = get_live(Set),      [{bs_get_tail,Src,Dst,Live}];  cg_instr(bs_get_position, [Ctx], Dst, Set) ->      Live = get_live(Set),      [{bs_get_position,Ctx,Dst,Live}]; +cg_instr(put_map, [{atom,assoc},SrcMap|Ss], Dst, Set) -> +    Live = get_live(Set), +    [{put_map_assoc,{f,0},SrcMap,Dst,Live,{list,Ss}}];  cg_instr(Op, Args, Dst, _Set) ->      cg_instr(Op, Args, Dst). diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index bf99e8fc26..878493e926 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -108,7 +108,8 @@ functions([], _Ps, _UseBSM3) -> [].               intervals=[] :: [{b_var(),[range()]}],               res=[] :: [{b_var(),reservation()}] | #{b_var():=reservation()},               regs=#{} :: #{b_var():=ssa_register()}, -             extra_annos=[] :: [{atom(),term()}] +             extra_annos=[] :: [{atom(),term()}], +             location :: term()              }).  -define(PASS(N), {N,fun N/1}). @@ -120,6 +121,7 @@ passes(Opts) ->            %% Preliminaries.            ?PASS(fix_bs),            ?PASS(sanitize), +          ?PASS(match_fail_instructions),            case FixTuples of                false -> ignore;                true -> ?PASS(fix_tuples) @@ -162,7 +164,9 @@ passes(Opts) ->  function(#b_function{anno=Anno,args=Args,bs=Blocks0,cnt=Count0}=F0,           Ps, UseBSM3) ->      try -        St0 = #st{ssa=Blocks0,args=Args,use_bsm3=UseBSM3,cnt=Count0}, +        Location = maps:get(location, Anno, none), +        St0 = #st{ssa=Blocks0,args=Args,use_bsm3=UseBSM3, +                  cnt=Count0,location=Location},          St = compile:run_sub_passes(Ps, St0),          #st{ssa=Blocks,cnt=Count,regs=Regs,extra_annos=ExtraAnnos} = St,          F1 = add_extra_annos(F0, ExtraAnnos), @@ -854,6 +858,114 @@ prune_phi(#b_set{args=Args0}=Phi, Reachable) ->                   gb_sets:is_element(Pred, Reachable)],      Phi#b_set{args=Args}. +%%% Rewrite certain calls to erlang:error/{1,2} to specialized +%%% instructions: +%%% +%%% erlang:error({badmatch,Value})       => badmatch Value +%%% erlang:error({case_clause,Value})    => case_end Value +%%% erlang:error({try_clause,Value})     => try_case_end Value +%%% erlang:error(if_clause)              => if_end +%%% erlang:error(function_clause, Args)  => jump FuncInfoLabel +%%% +%%% In SSA code, we represent those instructions as a 'match_fail' +%%% instruction with the name of the BEAM instruction as the first +%%% argument. + +match_fail_instructions(#st{ssa=Blocks0,args=Args,location=Location}=St) -> +    Ls = maps:to_list(Blocks0), +    Info = {length(Args),Location}, +    Blocks = match_fail_instrs_1(Ls, Info, Blocks0), +    St#st{ssa=Blocks}. + +match_fail_instrs_1([{L,#b_blk{is=Is0}=Blk}|Bs], Arity, Blocks0) -> +    case match_fail_instrs_blk(Is0, Arity, []) of +        none -> +            match_fail_instrs_1(Bs, Arity, Blocks0); +        Is -> +            Blocks = Blocks0#{L:=Blk#b_blk{is=Is}}, +            match_fail_instrs_1(Bs, Arity, Blocks) +    end; +match_fail_instrs_1([], _Arity, Blocks) -> Blocks. + +match_fail_instrs_blk([#b_set{op=put_tuple,dst=Dst, +                              args=[#b_literal{val=Tag},Val]}, +                       #b_set{op=call, +                              args=[#b_remote{mod=#b_literal{val=erlang}, +                                              name=#b_literal{val=error}}, +                                    Dst]}=Call|Is], +                      _Arity, Acc) -> +    match_fail_instr(Call, Tag, Val, Is, Acc); +match_fail_instrs_blk([#b_set{op=call, +                              args=[#b_remote{mod=#b_literal{val=erlang}, +                                              name=#b_literal{val=error}}, +                                    #b_literal{val={Tag,Val}}]}=Call|Is], +                      _Arity, Acc) -> +    match_fail_instr(Call, Tag, #b_literal{val=Val}, Is, Acc); +match_fail_instrs_blk([#b_set{op=call, +                              args=[#b_remote{mod=#b_literal{val=erlang}, +                                              name=#b_literal{val=error}}, +                                    #b_literal{val=if_clause}]}=Call|Is], +                      _Arity, Acc) -> +    I = Call#b_set{op=match_fail,args=[#b_literal{val=if_end}]}, +    reverse(Acc, [I|Is]); +match_fail_instrs_blk([#b_set{op=call,anno=Anno, +                              args=[#b_remote{mod=#b_literal{val=erlang}, +                                              name=#b_literal{val=error}}, +                                    #b_literal{val=function_clause}, +                                    Stk]}=Call], +                      {Arity,Location}, Acc) -> +    case match_fail_stk(Stk, Acc, [], []) of +        {[_|_]=Vars,Is} when length(Vars) =:= Arity -> +            case maps:get(location, Anno, none) of +                Location -> +                    I = Call#b_set{op=match_fail, +                                   args=[#b_literal{val=function_clause}|Vars]}, +                    Is ++ [I]; +                _ -> +                    %% erlang:error/2 has a different location than the +                    %% func_info instruction at the beginning of the function +                    %% (probably because of inlining). Keep the original call. +                    reverse(Acc, [Call]) +            end; +        _ -> +            %% Either the stacktrace could not be picked apart (for example, +            %% if the call to erlang:error/2 was handwritten) or the number +            %% of arguments in the stacktrace was different from the arity +            %% of the host function (because it is the implementation of a +            %% fun). Keep the original call. +            reverse(Acc, [Call]) +    end; +match_fail_instrs_blk([I|Is], Arity, Acc) -> +    match_fail_instrs_blk(Is, Arity, [I|Acc]); +match_fail_instrs_blk(_, _, _) -> +    none. + +match_fail_instr(Call, Tag, Val, Is, Acc) -> +    Op = case Tag of +             badmatch -> Tag; +             case_clause -> case_end; +             try_clause -> try_case_end; +             _ -> none +         end, +    case Op of +        none -> +            none; +        _ -> +            I = Call#b_set{op=match_fail,args=[#b_literal{val=Op},Val]}, +            reverse(Acc, [I|Is]) +    end. + +match_fail_stk(#b_var{}=V, [#b_set{op=put_list,dst=V,args=[H,T]}|Is], IAcc, VAcc) -> +    match_fail_stk(T, Is, IAcc, [H|VAcc]); +match_fail_stk(#b_literal{val=[H|T]}, Is, IAcc, VAcc) -> +    match_fail_stk(#b_literal{val=T}, Is, IAcc, [#b_literal{val=H}|VAcc]); +match_fail_stk(#b_literal{val=[]}, [], IAcc, VAcc) -> +    {reverse(VAcc),IAcc}; +match_fail_stk(T, [#b_set{op=Op}=I|Is], IAcc, VAcc) +  when Op =:= bs_get_tail; Op =:= bs_set_position -> +    match_fail_stk(T, Is, [I|IAcc], VAcc); +match_fail_stk(_, _, _, _) -> none. +  %%%  %%% Fix tuples.  %%% diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 28db8986ff..17ec986d82 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -860,8 +860,6 @@ asm_passes() ->         {unless,no_postopt,  	[{pass,beam_block},  	 {iff,dblk,{listing,"block"}}, -	 {unless,no_except,{pass,beam_except}}, -	 {iff,dexcept,{listing,"except"}},  	 {unless,no_jopt,{pass,beam_jump}},  	 {iff,djmp,{listing,"jump"}},  	 {unless,no_peep_opt,{pass,beam_peep}}, @@ -2095,7 +2093,6 @@ pre_load() ->  	 beam_block,  	 beam_clean,  	 beam_dict, -	 beam_except,  	 beam_flatten,  	 beam_jump,  	 beam_kernel_to_ssa, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index a086a3a8d3..9dc3b6e339 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -27,7 +27,6 @@  	     beam_clean,  	     beam_dict,  	     beam_disasm, -	     beam_except,  	     beam_flatten,  	     beam_jump,               beam_kernel_to_ssa, | 
