hipe_main.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 622 行 · 第 1/2 页
ERL
622 行
%% -*- erlang-indent-level: 2 -*-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $Id$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @doc This is the HiPE compiler's main "loop".%%%% <h3>Purpose</h3>%%%% <p> This module provides code which compiles a single Erlang%% function, represented as linear ICode all the way down to a linear%% native code representation (which depends on the 'hipe_target_arch'%% global variable). </p>%%%% @end%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=====================================================================-module(hipe_main).-export([compile_icode/3]).%%=====================================================================-ifndef(DEBUG).-define(DEBUG,1).-endif.-define(HIPE_INSTRUMENT_COMPILER, true). %% Turn on instrumentation.-include("../main/hipe.hrl").%%=====================================================================%% @spec compile_icode(MFA::mfa(),%% LinearIcode::term(),%% CompilerOptions::options()) ->%% {native,Platform,{unprofiled,NativeCode}} | {rtl,RTLCode}%%%% options() = [option()]%% option() = term()%%%% @type mfa() = {M::mod(),F::fun(),A::arity()}.%% A fully qualified function name.%%%% @type fun() = atom(). A function identifier.%%%% @type arity() = integer(). A function arity; always nonnegative.%%%% @doc Compiles the Icode (in linear form) of a single MFA down to%% native code for the platform of the target architecture.%% CompilerOptions influence the steps of this compilation process.%%%% <p> In particular, the compiler option '<code>to_rtl</code>' stops%% compilation after translation to RTL (in which case RTL code is%% generated). The compiler options must have already been expanded%% (cf. `<a href="hipe.html">hipe:expand_options</a>'). </p>compile_icode(MFA, LinearIcode, Options) -> compile_icode(MFA, LinearIcode, Options, get(hipe_debug)).%%--------------------------------------------------------------------%%%% The following constraints apply to the passes on Icode:%% %% 1. The no_comment pass must be done on linear form;%%%% 2. linear_to_cfg, which turns linear form into a CFG, must be%% performed before any of the passes on CFG form;%%%% 3. handle_exceptions must be performed before icode_ssa;%%%% 4. split_arith should be performed after icode_ssa for%% effectiveness reasons (and perhaps to work at all);%%%% 5. remove_trivial_bbs should be performed last to tidy up the CFG.%%%%---------------------------------------------------------------------compile_icode(MFA, LinearIcode0, Options, DebugState) -> %% Set up gensym with the right ranges for this function. {_LMin,LMax} = hipe_icode:icode_label_range(LinearIcode0), hipe_gensym:set_label(icode,LMax+1), {_VMin,VMax} = hipe_icode:icode_var_range(LinearIcode0), hipe_gensym:set_var(icode,VMax+1), %%hipe_icode_pp:pp(LinearIcode0), ?opt_start_timer("Icode"), LinearIcode1 = icode_no_comment(LinearIcode0, Options), IcodeCfg0 = icode_linear_to_cfg(LinearIcode1, Options), %%hipe_icode_cfg:pp(IcodeCfg1), IcodeCfg1 = icode_handle_exceptions(IcodeCfg0, MFA, Options), IcodeCfg2 = icode_binary_pass(IcodeCfg1, Options), IcodeCfg3 = icode_inline_bifs(IcodeCfg2, Options), icode_pp(IcodeCfg3, MFA, proplists:get_value(pp_icode, Options),Options), case icode_ssa(IcodeCfg3, MFA, Options) of {dialyzer, IcodeSSA} -> {dialyzer, IcodeSSA}; IcodeCfg4 -> compile_icode_2(MFA, IcodeCfg4, Options, DebugState) end.compile_icode_2(MFA, IcodeCfg4, Options, DebugState) -> IcodeCfg5 = icode_split_arith(IcodeCfg4, MFA, Options), icode_pp(IcodeCfg5, MFA, proplists:get_value(pp_icode_split_arith, Options),Options), IcodeCfg6 = icode_heap_test(IcodeCfg5, Options), IcodeCfg7 = icode_remove_trivial_bbs(IcodeCfg6, Options), icode_pp(IcodeCfg7, MFA, proplists:get_value(pp_opt_icode, Options),Options), icode_liveness_pp(IcodeCfg7, MFA, Options), FinalIcode = hipe_icode_cfg:cfg_to_linear(IcodeCfg7), ?opt_stop_timer("Icode"), ?option_time(LinearRTL=icode_to_rtl(MFA,FinalIcode,Options), "RTL", Options), case proplists:get_bool(to_rtl, Options) of false -> rtl_to_native(MFA, LinearRTL, Options, DebugState); true -> put(hipe_debug, DebugState), {rtl, LinearRTL} end.%%----------------------------------------------------------------%%%% Icode passes%%%%----------------------------------------------------------------icode_no_comment(LinearIcode, Options) -> case proplists:get_bool(remove_comments, Options) of true -> ?option_time(hipe_icode:strip_comments(LinearIcode), "Icode remove comments", Options); _ -> LinearIcode end.icode_linear_to_cfg(LinearIcode, Options) -> ?option_time(hipe_icode_cfg:linear_to_cfg(LinearIcode), "transform linear Icode to CFG", Options).%% The binary_pass needs to occur before the handle_exceptions pass%% because it assumes that all binary matches have a common end%% fail-label. This is no longer true after fixing up the catches.icode_binary_pass(IcodeCfg, Options) -> ?option_time(hipe_icode_bincomp:simple(IcodeCfg), "Icode binary pass", Options).icode_handle_exceptions(IcodeCfg, MFA, Options) -> debug("Icode fix catches: ~w~n", [MFA], Options), ?option_time(hipe_icode_exceptions:fix_catches(IcodeCfg), "Icode fix catches", Options).icode_inline_bifs(IcodeCfg, Options) -> case proplists:get_bool(icode_inline_bifs, Options) of true -> ?option_time(hipe_icode_inline_bifs:cfg(IcodeCfg), "Icode inline bifs", Options); false -> IcodeCfg end.%%---------------------------------------------------------------------icode_split_arith(IcodeCfg, MFA, Options) -> case proplists:get_bool(split_arith, Options) orelse proplists:get_bool(split_arith_unsafe, Options) of true -> ?option_time(hipe_icode_split_arith:cfg(IcodeCfg, MFA, Options), "Icode split arith", Options); _ -> IcodeCfg end.icode_heap_test(IcodeCfg, Options) -> ?option_time(hipe_icode_heap_test:cfg(IcodeCfg), "Icode heap_test", Options).icode_remove_trivial_bbs(IcodeCfg, Options) -> ?option_time(hipe_icode_cfg:remove_trivial_bbs(IcodeCfg), "Icode trivial BB removal", Options).icode_pp(IcodeCfg, MFA, PrintOption, Options) -> perform_io( fun() -> case PrintOption of true -> hipe_icode_cfg:pp(IcodeCfg); {only,Lst} when is_list(Lst) -> case lists:member(MFA,Lst) of true -> hipe_icode_cfg:pp(IcodeCfg); false -> ok end; {only,MFA} -> hipe_icode_cfg:pp(IcodeCfg); {file,FileName} -> {ok,File} = file:open(FileName, [write,append]), hipe_icode_cfg:pp(File, IcodeCfg); _ -> ok end end, Options).icode_liveness_pp(IcodeCfg, MFA, Options) -> perform_io( fun() -> case proplists:get_value(pp_icode_liveness, Options) of true -> hipe_icode_liveness:pp(IcodeCfg); {only,Lst} when is_list(Lst) -> case lists:member(MFA,Lst) of true -> hipe_icode_liveness:pp(IcodeCfg); false -> ok end; {only,MFA} -> hipe_icode_liveness:pp(IcodeCfg); _ -> ok end end,Options).perform_io(Fun,Opts) -> case proplists:get_value(pp_server,Opts) of Pid when is_pid(Pid) -> Pid ! {print,Fun}; _ -> Fun() end.%%--------------------------------------------------------------------%%%% Icode passes on SSA form. The following constraints are applicable:%% %% 1. ssa_convert must be first and ssa_unconvert last%% %% 2. ssa_dead_code must be run after the other passes%%%% 3. The present order was chosen to maximize effectiveness as%% ssa_const_prop might make ssa_type_info more effective%% %% 4. ssa_check could be put in between all passes to make sure that%% they preserve SSA-ness%%%%---------------------------------------------------------------------icode_ssa(IcodeCfg0, MFA, Options) -> ?opt_start_timer("Icode SSA-passes"), IcodeSSA0 = icode_ssa_convert(IcodeCfg0, Options), IcodeSSA2 = icode_ssa_const_prop(IcodeSSA0, Options), icode_pp(IcodeSSA0, MFA, proplists:get_value(pp_icode_ssa,Options),Options), IcodeSSA3 = icode_ssa_copy_prop(IcodeSSA2, Options), case proplists:get_bool(dialyzer, Options) of true -> {dialyzer, IcodeSSA3}; false -> IcodeSSA4 = icode_ssa_type(IcodeSSA3, MFA, Options), IcodeSSA5 = icode_ssa_dead_code_elimination(IcodeSSA4, Options), IcodeSSA6 = icode_ssa_struct_reuse(IcodeSSA5, Options), icode_ssa_check(IcodeSSA6, Options), %% just for sanity icode_pp(IcodeSSA6, MFA, proplists:get_value(pp_icode_ssa,Options),Options), IcodeCfg = icode_ssa_unconvert(IcodeSSA6, Options), ?opt_stop_timer("Icode SSA-passes"), IcodeCfg end.icode_ssa_type(IcodeSSA, MFA, Options) -> case proplists:get_value(icode_type, Options) of false -> IcodeSSA; undefined -> IcodeSSA; true -> AnnIcode1 = icode_ssa_type_info(IcodeSSA, MFA, Options), AnnIcode2 = case proplists:get_bool(inline_fp, Options) of true -> hipe_icode_fp:cfg(AnnIcode1); false -> AnnIcode1 end, AnnIcode3 = icode_range_analysis(AnnIcode2,MFA,Options), icode_pp(AnnIcode3,MFA,proplists:get_value(pp_range_icode,Options),Options), hipe_icode_type:unannotate_cfg(AnnIcode3) end.icode_ssa_convert(IcodeCfg, Options) -> ?option_time(hipe_icode_ssa:convert(IcodeCfg), "Icode SSA conversion", Options).icode_ssa_const_prop(IcodeSSA, Options) -> case proplists:get_bool(icode_ssa_const_prop,Options) of true -> ?option_time(Tmp=hipe_icode_ssa_const_prop:sparse_cond_const_propagate(IcodeSSA), "Icode SSA sparse conditional constant propagation", Options), ?option_time(hipe_icode_ssa:remove_dead_code(Tmp), "Icode SSA dead code elimination pass 1", Options); false -> IcodeSSA end.icode_ssa_copy_prop(IcodeSSA, Options) -> case proplists:get_value(icode_ssa_copy_prop, Options) of true -> ?option_time(hipe_icode_ssa_copy_prop:cfg(IcodeSSA), "Icode SSA copy propagation", Options); _ -> IcodeSSA end.icode_ssa_struct_reuse(IcodeSSA, Options) -> case proplists:get_value(icode_ssa_struct_reuse, Options) of
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?