diff options
Diffstat (limited to 'lib/compiler/src/beam_type.erl')
-rw-r--r-- | lib/compiler/src/beam_type.erl | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index acaf3ede66..fc2c7a991b 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. 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. @@ -26,6 +26,11 @@ -import(lists, [filter/2,foldl/3,keyfind/3,member/2, reverse/1,reverse/2,sort/1]). +-define(UNICODE_INT, {integer,{0,16#10FFFF}}). + +-spec module(beam_utils:module_code(), [compile:option()]) -> + {'ok',beam_utils:module_code()}. + module({Mod,Exp,Attr,Fs0,Lc}, _Opts) -> Fs = [function(F) || F <- Fs0], {ok,{Mod,Exp,Attr,Fs,Lc}}. @@ -34,7 +39,8 @@ function({function,Name,Arity,CLabel,Asm0}) -> try Asm1 = beam_utils:live_opt(Asm0), Asm2 = opt(Asm1, [], tdb_new()), - Asm = beam_utils:delete_live_annos(Asm2), + Asm3 = beam_utils:live_opt(Asm2), + Asm = beam_utils:delete_live_annos(Asm3), {function,Name,Arity,CLabel,Asm} catch Class:Error -> @@ -111,14 +117,6 @@ simplify_basic_1([{test,is_tuple,_,[R]}=I|Is], Ts, Acc) -> {tuple,_,_} -> simplify_basic_1(Is, Ts, Acc); _ -> simplify_basic_1(Is, Ts, [I|Acc]) end; -simplify_basic_1([{test,test_arity,_,[R,Arity]}=I|Is], Ts0, Acc) -> - case tdb_find(R, Ts0) of - {tuple,Arity,_} -> - simplify_basic_1(Is, Ts0, Acc); - _Other -> - Ts = update(I, Ts0), - simplify_basic_1(Is, Ts, [I|Acc]) - end; simplify_basic_1([{test,is_map,_,[R]}=I|Is], Ts0, Acc) -> case tdb_find(R, Ts0) of map -> simplify_basic_1(Is, Ts0, Acc); @@ -141,14 +139,6 @@ simplify_basic_1([{test,is_eq_exact,Fail,[R,{atom,_}=Atom]}=I|Is0], Ts0, Acc0) - end, Ts = update(I, Ts0), simplify_basic_1(Is0, Ts, Acc); -simplify_basic_1([{test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I|Is], Ts0, Acc) -> - case tdb_find(R, Ts0) of - {tuple,Arity,[Tag]} -> - simplify_basic_1(Is, Ts0, Acc); - _Other -> - Ts = update(I, Ts0), - simplify_basic_1(Is, Ts, [I|Acc]) - end; simplify_basic_1([{select,select_val,Reg,_,_}=I0|Is], Ts, Acc) -> I = case tdb_find(Reg, Ts) of {integer,Range} -> @@ -361,6 +351,8 @@ flt_need_heap_2({set,_,_,get_list}, H, Fl) -> {[],H,Fl}; flt_need_heap_2({set,_,_,{try_catch,_,_}}, H, Fl) -> {[],H,Fl}; +flt_need_heap_2({set,_,_,init}, H, Fl) -> + {[],H,Fl}; %% All other instructions should cause the insertion of an allocation %% instruction if needed. flt_need_heap_2(_, H, Fl) -> @@ -490,6 +482,10 @@ update({test,test_arity,_Fail,[Src,Arity]}, Ts0) -> tdb_update([{Src,{tuple,Arity,[]}}], Ts0); update({test,is_map,_Fail,[Src]}, Ts0) -> tdb_update([{Src,map}], Ts0); +update({get_map_elements,_,Src,{list,Elems0}}, Ts0) -> + {_Ss,Ds} = beam_utils:split_even(Elems0), + Elems = [{Dst,kill} || Dst <- Ds], + tdb_update([{Src,map}|Elems], Ts0); update({test,is_nonempty_list,_Fail,[Src]}, Ts0) -> tdb_update([{Src,nonempty_list}], Ts0); update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts) -> @@ -503,10 +499,39 @@ update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts) -> end; update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) -> tdb_update([{Src,{tuple,Arity,[Tag]}}], Ts); -update({test,_Test,_Fail,_Other}, Ts) -> - Ts; + +%% Binary matching + update({test,bs_get_integer2,_,_,Args,Dst}, Ts) -> tdb_update([{Dst,get_bs_integer_type(Args)}], Ts); +update({test,bs_get_utf8,_,_,_,Dst}, Ts) -> + tdb_update([{Dst,?UNICODE_INT}], Ts); +update({test,bs_get_utf16,_,_,_,Dst}, Ts) -> + tdb_update([{Dst,?UNICODE_INT}], Ts); +update({test,bs_get_utf32,_,_,_,Dst}, Ts) -> + tdb_update([{Dst,?UNICODE_INT}], Ts); +update({bs_init,_,_,_,_,Dst}, Ts) -> + tdb_update([{Dst,kill}], Ts); +update({bs_put,_,_,_}, Ts) -> + Ts; +update({bs_save2,_,_}, Ts) -> + Ts; +update({bs_restore2,_,_}, Ts) -> + Ts; +update({bs_context_to_binary,Dst}, Ts) -> + tdb_update([{Dst,kill}], Ts); +update({test,bs_start_match2,_,_,_,Dst}, Ts) -> + tdb_update([{Dst,kill}], Ts); +update({test,bs_get_binary2,_,_,_,Dst}, Ts) -> + tdb_update([{Dst,kill}], Ts); +update({test,bs_get_float2,_,_,_,Dst}, Ts) -> + tdb_update([{Dst,float}], Ts); + +update({test,_Test,_Fail,_Other}, Ts) -> + Ts; + +%% Calls + update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) -> case is_math_bif(Math, Ar) of true -> tdb_update([{{x,0},float}], Ts); @@ -533,9 +558,10 @@ update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) -> update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts); update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts); update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts); +update({call_fun, _}, Ts) -> tdb_kill_xregs(Ts); +update({apply, _}, Ts) -> tdb_kill_xregs(Ts); + update({line,_}, Ts) -> Ts; -update({bs_save2,_,_}, Ts) -> Ts; -update({bs_restore2,_,_}, Ts) -> Ts; %% The instruction is unknown. Kill all information. update(_I, _Ts) -> tdb_new(). @@ -592,6 +618,9 @@ is_math_bif(log10, 1) -> true; is_math_bif(sqrt, 1) -> true; is_math_bif(atan2, 2) -> true; is_math_bif(pow, 2) -> true; +is_math_bif(ceil, 1) -> true; +is_math_bif(floor, 1) -> true; +is_math_bif(fmod, 2) -> true; is_math_bif(pi, 0) -> true; is_math_bif(_, _) -> false. @@ -676,6 +705,9 @@ op_type('bsr') -> integer; op_type('div') -> integer; op_type(_) -> unknown. +flush(Rs, [{set,[_],[_,_,_],{bif,is_record,_}}|_]=Is0, Acc0) -> + Acc = flush_all(Rs, Is0, Acc0), + {[],Acc}; flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) -> Acc = flush_all(Rs, Is0, Acc0), {[],Acc}; @@ -882,10 +914,10 @@ merge_type_info({tuple,Sz1,[]}, {tuple,_Sz2,First}=Tuple2) -> merge_type_info({tuple,Sz1,First}, Tuple2); merge_type_info({tuple,_Sz1,First}=Tuple1, {tuple,Sz2,_}) -> merge_type_info(Tuple1, {tuple,Sz2,First}); -merge_type_info(integer, {integer,_}=Int) -> - Int; -merge_type_info({integer,_}=Int, integer) -> - Int; +merge_type_info(integer, {integer,_}) -> + integer; +merge_type_info({integer,_}, integer) -> + integer; merge_type_info({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) -> {integer,{max(Min1, Min2),min(Max1, Max2)}}; merge_type_info(NewType, _) -> |