hipe_icode_range.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,642 行 · 第 1/4 页
ERL
1,642 行
%%%-------------------------------------------------------------------%%% File : hipe_icode_range.erl%%% Author : Per Gustafsson <pergu@it.uu.se>%%% Description : %%%%%% Created : 12 Mar 2007 by Per Gustafsson <pergu@it.uu.se>%%%--------------------------------------------------------------------module(hipe_icode_range).-export([cfg/3,pp_ann/1]).%%=====================================================================%% Icode Coordinator Callbacks%%=====================================================================-export([replace_nones/1, update__info/2, new__info/1, return__info/1, return_none/0, return_none_args/2, return_any_args/2]).%%=====================================================================-import(erl_types, [t_any/0, t_inf/2, t_integer/0, t_from_range_unsafe/2, t_to_string/1, t_none/0, number_min/1, number_max/1 ]).-record(ann, {range, type, count}).-record(range, {range, other}).-define(WIDEN, 1).-include("hipe_icode.hrl").-include("hipe_icode_primops.hrl").-include("../main/hipe.hrl").-define(TAG_IMMED1_SIZE, 4).-define(BITS, 64).cfg(Cfg, IcodeFun, Options) -> case proplists:get_bool(concurrent_comp, Options) of true -> concurrent_cfg(Cfg, IcodeFun, Options, proplists:get_value(icode_range_server, Options)); false -> ordinary_cfg(Cfg, IcodeFun, Options) end.concurrent_cfg(Cfg, MFA, Options, CompServer) -> CompServer ! {ready, {MFA,self()}}, {ArgsFun,CallFun,FinalFun} = do_analysis(Cfg, MFA, Options), do_rewrite(Cfg, MFA, Options, ArgsFun, CallFun, FinalFun).do_analysis(Cfg, MFA, Options) -> receive {analyse, {ArgsFun, CallFun, FinalFun}} -> analyse(Cfg, {MFA, ArgsFun, CallFun, FinalFun}), do_analysis(Cfg, MFA, Options); {done, {NewArgsFun, NewCallFun, NewFinalFun}} -> {NewArgsFun, NewCallFun, NewFinalFun} end.do_rewrite(Cfg, MFA, Options, ArgsFun, CallFun, FinalFun) -> common_rewrite(Cfg, MFA, Options, {MFA, ArgsFun, CallFun, FinalFun}). ordinary_cfg(Cfg, MFA, Options) -> Data = make_data(Cfg,MFA), common_rewrite(Cfg, MFA, Options, Data). common_rewrite(Cfg, _MFA, _Options, Data) -> State = analyse(Cfg, Data), State2 = rewrite_blocks(State), Cfg1 = state__cfg(State2), Cfg2 = hipe_icode_cfg:remove_unreachable_code(Cfg1), Cfg3 = convert_cfg_to_types(Cfg2), hipe_icode_type:specialize(Cfg3).make_data(Cfg, {_M,_F,A}=MFA) -> NoArgs = case hipe_icode_cfg:is_closure(Cfg) of true -> hipe_icode_cfg:closure_arity(Cfg)+1; false -> A end, Args = lists:duplicate(NoArgs, any_type()), ArgsFun = fun(_,_) -> Args end, CallFun = fun(_,_) -> [any_type()] end, FinalFun = fun(_,_) -> ok end, {MFA,ArgsFun,CallFun,FinalFun}.analyse(Cfg, Data={MFA,_,_,_}) -> try State = state__init(Cfg,Data), Work = init_work(State), NewState = analyse_blocks(State,Work,false), (state__resultaction(NewState))(MFA,state__ret_type(NewState)), NewState catch throw:no_input -> ok end.rewrite_blocks(State) -> Cfg = state__cfg(State), Start = hipe_icode_cfg:start_label(Cfg), rewrite_blocks([Start], State, [Start]).rewrite_blocks([Next|Rest], State, Visited) -> Info = state__info_in(State, Next), {NewState, NewLabels} = analyse_block(Next, Info, State, true), NewLabelsSet = ordsets:from_list(NewLabels), RealNew = ordsets:subtract(NewLabelsSet, Visited), NewVisited = ordsets:union([RealNew,Visited,[Next]]), NewWork = ordsets:union([RealNew,Rest]), rewrite_blocks(NewWork, NewState, NewVisited);rewrite_blocks([], State, _) -> State.analyse_blocks(State, Work, Rewrite) -> case get_work(Work) of fixpoint -> State; {Label, NewWork} -> Info = state__info_in(State, Label), %%if Label == 20 -> io:format("Infoin: ~p~n", [gb_trees:to_list(Info)]); true -> ok end, {NewState, NewLabels} = try analyse_block(Label, Info, State, Rewrite) catch throw:none_range -> {State,[]} end, NewWork2 = add_work(NewWork, NewLabels), analyse_blocks(NewState, NewWork2, Rewrite) end.analyse_block(Label, Info, State, Rewrite) -> case state__bb(State, Label) of not_found -> io:format("Unknown Label: ~w~n", [Label]), {State,[]}; BB -> Code = hipe_bb:code(BB), {NewCode, InfoList, RetType} = analyse_BB(Code,Info,[],Rewrite,state__lookupfun(State)), State1 = state__bb_add(State, Label, hipe_bb:mk_bb(NewCode)), State2 = state__ret_type_update(State1, RetType), state__update_info(State2, InfoList, Rewrite) end.analyse_BB([Last], Info, Code, Rewrite, LookupFun) -> %%io:format("I: ~w~n",[Last]), {{NewI,InfoList},RetType} = analyse_last_insn(Last, Info, Rewrite, LookupFun), {lists:reverse([NewI|Code]), InfoList, RetType};analyse_BB([Insn|InsnList], Info, Code, Rewrite, LookupFun) -> {NewInfo,NewI} = analyse_insn(Insn, Info, LookupFun), analyse_BB(InsnList, NewInfo, [NewI|Code], Rewrite, LookupFun).analyse_insn(I, Info, LookupFun) -> %%io:format("~w Info: ~p~n",[I,Info]), NewI = handle_args(I,Info), FinalI = case NewI of #call{} -> analyse_call(NewI, LookupFun); #move{} -> analyse_move(NewI); #phi{} -> analyse_phi(NewI); #fmove{} -> analyse_fmove(NewI); #begin_handler{} -> analyse_begin_handler(NewI) end, {enter_vals(FinalI,Info), FinalI}.handle_args(I, Info) -> WidenFun = fun update_three/3, handle_args(I, Info, WidenFun).handle_args(I, Info, WidenFun) -> Uses = hipe_icode:uses(I), PresentRanges = [lookup(V,Info) || V <- Uses], %%io:format("Uses: ~p~nRanges: ~p~n",[Uses,PresentRanges]), JoinFun = fun(Var, Range) -> update_info(Var, Range, WidenFun) end, NewUses = lists:zipwith(JoinFun, Uses, PresentRanges), hipe_icode:subst_uses(lists:zip(Uses, NewUses),I).join_info(Ann = #ann{range=R1,type=Type,count=?WIDEN}, R2, Fun) -> Ann#ann{range = Fun(R1,R2,range_from_type(Type))};join_info(Ann = #ann{range=R1,type=Type,count=C}, R2, _Fun) when C < ?WIDEN -> case join_three(R1, R2, range_from_type(Type)) of R1 -> Ann; NewR -> Ann#ann{range = NewR, count=C+1} end.join_three(R1,R2,R3) -> inf(sup(R1,R2),R3).update_info(Var, Range) -> update_info(Var, Range, fun update_three/3).update_info({var,Name,Ann}, R, Fun) -> {var,Name,update_info1(Ann,R,Fun)};update_info({reg,Name}, _R, _) -> {reg,Name};update_info({fvar,Name}, _R, _) -> {fvar,Name}.update_info1(Ann = #ann{range=R1,type=Type,count=?WIDEN}, R2, Fun) -> Ann#ann{range = Fun(R1,R2,range_from_type(Type))};update_info1(Ann = #ann{range=R1,type=Type,count=C}, R2, _Fun) -> case update_three(R1, R2, range_from_type(Type)) of R1 -> Ann; NewR -> Ann#ann{range = NewR, count=C+1} end;update_info1(Type,R2, _Fun) -> #ann{range = inf(range_from_type(Type),R2), type = Type, count=1}.update_three(_R1,R2,R3) -> inf(R2,R3).safe_widen(#range{range=Old},#range{range=New},T = #range{range=Wide}) -> ResRange = case {Old,New,Wide} of {{Min,Max1},{Min,Max2},{_,Max}} -> case inf_geq(OMax = next_up_limit(inf_max([Max1,Max2])),Max) of true -> {Min,Max}; false -> {Min,OMax} end; {{Min1,Max},{Min2,Max},{Min,_}} -> case inf_geq(Min, OMin = next_down_limit(inf_min([Min1,Min2]))) of true -> {Min,Max}; false -> {OMin,Max} end; {{Min1,Max1},{Min2,Max2},{Min,Max}} -> RealMax = case inf_geq(OMax = next_up_limit(inf_max([Max1,Max2])),Max) of true -> Max; false -> OMax end, RealMin = case inf_geq(Min, OMin = next_down_limit(inf_min([Min1,Min2]))) of true -> Min; false -> OMin end, {RealMin,RealMax}; _ -> Wide end, T#range{range=ResRange}.widen(#range{range=Old},#range{range=New},T = #range{range=Wide}) -> ResRange = case {Old,New,Wide} of {{Min,_},{Min,Max2},{_,Max}} -> case inf_geq(OMax = next_up_limit(Max2),Max) of true -> {Min,Max}; false -> {Min,OMax} end; {{_,Max},{Min2,Max},{Min,_}} -> case inf_geq(Min, OMin = next_down_limit(Min2)) of true -> {Min,Max}; false -> {OMin,Max} end; {_,{Min2,Max2},{Min,Max}} -> RealMax = case inf_geq(OMax = next_up_limit(Max2),Max) of true -> Max; false -> OMax end, RealMin = case inf_geq(Min, OMin = next_down_limit(Min2)) of true -> Min; false -> OMin end, {RealMin,RealMax}; _ -> Wide end, T#range{range=ResRange}. analyse_call(Call, LookupFun) -> Args = hipe_icode:args(Call), Dsts = hipe_icode:call_dstlist(Call), Fun = hipe_icode:call_fun(Call), Type = hipe_icode:call_type(Call), DstRange = analyse_call_or_enter_fun(Fun, Args, Type, LookupFun), NewDefs = [update_info(Var,DstRange) || Var <- Dsts], hipe_icode:subst_defines(lists:zip(Dsts,NewDefs),Call).analyse_fmove(FMove) -> Dst = hipe_icode:fmove_dst(FMove), DstRange = none_range(), NewDst = update_info(Dst,DstRange), hipe_icode:subst_defines([{Dst,NewDst}],FMove).analyse_move(Move) -> Src = hipe_icode:move_src(Move), Dst = hipe_icode:move_dst(Move), Range = get_range_from_arg(Src), NewDst = update_info(Dst,Range), hipe_icode:subst_defines([{Dst,NewDst}],Move).analyse_begin_handler(Handler) -> SubstList = [{Dst,update_info(Dst,any_type())} || Dst <- hipe_icode:begin_handler_dstlist(Handler)], hipe_icode:subst_defines(SubstList,Handler). analyse_phi(Phi) -> {_, Args} = lists:unzip(hipe_icode:phi_arglist(Phi)), Dst = hipe_icode:phi_dst(Phi), Arg_ranges = get_range_from_args(Args), %%%%io:format("Phi-Arg_ranges: ~p ~n", [Arg_ranges]), DstRange = sup(Arg_ranges), NewDst = update_info(Dst,DstRange,fun widen/3), hipe_icode:subst_defines([{Dst,NewDst}],Phi).analyse_last_insn(I, Info, Rewrite, LookupFun) -> %%io:format("~w Info: ~p~n",[I,Info]), NewI = handle_args(I,Info), %%io:format("~w -> ~w~n",[NewI,I]), case NewI of #return{} -> analyse_return(NewI, Info); #enter{} -> analyse_enter(NewI, Info, LookupFun); #switch_val{} -> {analyse_switch_val(NewI, Info, Rewrite),[none_type()]}; #'if'{} -> {analyse_if(NewI, Info, Rewrite),[none_type()]}; #goto{} -> {analyse_goto(NewI, Info),[none_type()]}; #type{} -> {analyse_type(NewI, Info, Rewrite),[none_type()]}; #fail{} -> {analyse_fail(NewI, Info),[none_type()]}; #call{} -> {analyse_last_call(NewI, Info, LookupFun),[none_type()]}; #switch_tuple_arity{} -> {analyse_switch_tuple_arity(NewI, Info),[none_type()]}; #begin_try{} -> {analyse_begin_try(NewI, Info),[none_type()]} end.analyse_return(Insn, _Info) -> RetRange = get_range_from_args(hipe_icode:return_vars(Insn)), {{Insn,[]},RetRange}. analyse_enter(Insn, _Info, LookupFun) -> Args = hipe_icode:args(Insn), Fun = hipe_icode:enter_fun(Insn), CallType = hipe_icode:enter_type(Insn), RetRange = analyse_call_or_enter_fun(Fun,Args,CallType,LookupFun), {{Insn,[]},[RetRange]}.analyse_switch_val(Switch, Info, Rewrite) -> Arg = hipe_icode:switch_val_arg(Switch), SwitchRange = get_range_from_arg(Arg), Cases = hipe_icode:switch_val_cases(Switch), {FailRange, LabelRangeList} = get_range_label_list(Cases, SwitchRange, []), case range__is_none(FailRange) of true -> InfoList = update_infos(Arg, Info, LabelRangeList), if Rewrite -> {update_switch(Switch,LabelRangeList,false),InfoList}; true -> {Switch,InfoList} end; false -> FailLabel = hipe_icode:switch_val_fail_label(Switch), InfoList = update_infos(Arg, Info, [{FailRange, FailLabel}|LabelRangeList]), if Rewrite -> {update_switch(Switch,LabelRangeList,true), InfoList}; true -> {Switch,InfoList} end end.update_infos(Arg, Info, [{Range, Label}|Rest]) -> [{Label,enter_define({Arg,Range},Info)} | update_infos(Arg,Info,Rest)];update_infos(_, _, []) -> [].get_range_label_list([{Val,Label}|Cases],SRange,Acc) -> VRange = get_range_from_arg(Val), None = none_type(), case inf(SRange, VRange) of None -> get_range_label_list(Cases, SRange, Acc); ResRange -> get_range_label_list(Cases, SRange, [{ResRange,Label}|Acc]) end;get_range_label_list([], SRange, Acc) -> {PointTypes, _} = lists:unzip(Acc), {remove_point_types(SRange, PointTypes), Acc}.update_switch(Switch, LabelRangeList, KeepFail) -> S2 = case label_range_list_to_cases(LabelRangeList,[]) of no_update -> Switch; Cases -> hipe_icode:switch_val_cases_update(Switch, Cases) end, if KeepFail -> S2; true -> S2 end.label_range_list_to_cases([{#range{range={C,C},other=false},Label}|Rest], Acc) when is_integer(C) -> label_range_list_to_cases(Rest,[{hipe_icode:mk_const(C),Label}|Acc]);label_range_list_to_cases([{_NotAConstantRange,_Label}|_Rest],_Acc) -> no_update;label_range_list_to_cases([],Acc) -> lists:reverse(Acc). analyse_switch_tuple_arity(Switch, Info) -> Arg = hipe_icode:switch_tuple_arity_arg(Switch), NewInfo = enter_define({Arg,get_range_from_arg(Arg)},Info), Cases = hipe_icode:switch_tuple_arity_cases(Switch), Fail = hipe_icode:switch_tuple_arity_fail_label(Switch), {_, Case_labels} = lists:unzip(Cases), Labels = [Fail|Case_labels], {Switch,[{Label,NewInfo} || Label <- Labels]}.analyse_goto(Insn, Info) -> GotoLabel = hipe_icode:goto_label(Insn), {Insn,[{GotoLabel,Info}]}.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?