hipe.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,594 行 · 第 1/4 页
ERL
1,594 行
fun() -> hipe_icode_coordinator:coordinate( CallGraph,Escaping, NonEscaping,hipe_icode_type) end, TypeServer = spawn_link(TypeServerFun), PPServerFun = fun() -> pp_server_start(Opts) end, PPServer = spawn_link(PPServerFun), RangeServerFun = fun() -> hipe_icode_coordinator:coordinate( CallGraph,Escaping, NonEscaping,hipe_icode_range) end, RangeServer = spawn_link(RangeServerFun), NewOpts = [{icode_range_server,RangeServer}, {icode_type_server,TypeServer}, {pp_server,PPServer}|Opts], CompFuns = [fun() -> set_architecture(NewOpts), pre_init(NewOpts), init(NewOpts), Self ! finalize_fun_sequential(IcodeFun,NewOpts) end || IcodeFun <- MfaIcodeList], [spawn_link(Fun) || Fun <- CompFuns], Final = [receive Res when element(1,Res) =:= MFA -> Res end || {MFA,_} <- MfaIcodeList], [stop_and_wait(Pid) || Pid <- [PPServer,TypeServer,RangeServer]], Final; [] -> [] end.stop_and_wait(Pid) -> Pid ! {stop,self()}, receive _ -> ok end.finalize_fun_sequential({MFA, Icode}, Opts) -> {T1,_} = erlang:statistics(runtime), ?when_option(verbose, Opts, ?debug_msg("Compiling ~w",[MFA])), case catch hipe_main:compile_icode(MFA, Icode, Opts) of {native, Platform, {unprofiled,Code}} -> {T2,_} = erlang:statistics(runtime), ?when_option(verbose, Opts, ?debug_untagged_msg(" in ~.2f s\n", [(T2-T1)/1000])), case Platform of ultrasparc -> {Entry,Ct} = Code, {MFA,Entry,Ct}; powerpc -> {MFA, Code}; arm -> {MFA, Code}; x86 -> {MFA, Code}; amd64 -> {MFA, Code} end; {rtl, LinearRtl} -> io:format("~p~n", [LinearRtl]), {MFA, LinearRtl}; {dialyzer, IcodeSSA} -> {MFA, IcodeSSA}; {native, X} -> ?error_msg("ERROR: unknown native code format: ~P.\n",[X]), ?EXIT(unknown_format); {'EXIT', Error} -> ?when_option(verbose, Opts,?debug_untagged_msg("\n",[])), ?error_msg("ERROR: ~p~n",[Error]), ?EXIT(Error) end.pp_server_start(Opts) -> set_architecture(Opts), garbage_collect(), pp_server().pp_server() -> receive {print,Fun} -> Fun(),pp_server(); {stop,Pid} -> Pid ! {done,self()}; _ -> pp_server() end.icode_multret(List, Mod, Opts, Exports) -> case proplists:get_bool(icode_multret, Opts) of true -> hipe_icode_mulret:mult_ret(List, Mod, Opts, Exports); false -> List end.maybe_load(Mod, Bin, WholeModule, Opts) -> case proplists:get_bool(load, Opts) of false -> ok; true -> ?when_option(verbose, Opts, ?debug_msg("Loading/linking\n", [])), do_load(Mod, Bin, WholeModule) end.do_load(Mod, Bin, WholeModule) -> HostArch = get(hipe_host_arch), TargetArch = get(hipe_target_arch), %% Make sure we can do the load. if HostArch =/= TargetArch -> ?EXIT({host_and_target_arch_differ,HostArch,TargetArch}); true -> ok end, case WholeModule of false -> %% In this case, the emulated code for the module must be loaded. code:ensure_loaded(Mod), code:load_native_partial(Mod, Bin); _ -> case code:is_sticky(Mod) of true -> %% Don't purge or register sticky mods; just load native. code:load_native_sticky(Mod, Bin, WholeModule); false -> %% Normal loading of a whole module Architecture = erlang:system_info(hipe_architecture), ChunkName = hipe_unified_loader:chunk_name(Architecture), {ok,_,Chunks0} = beam_lib:all_chunks(WholeModule), Chunks = [{ChunkName,Bin}|lists:keydelete(ChunkName,1,Chunks0)], {ok,BeamPlusNative} = beam_lib:build_module(Chunks), code:load_binary(Mod,code:which(Mod),BeamPlusNative) end end.assemble(CompiledCode, Closures, Exports, Options) -> case get(hipe_target_arch) of ultrasparc -> hipe_sparc_assemble:assemble(CompiledCode, Closures, Exports, Options); powerpc -> hipe_ppc_assemble:assemble(CompiledCode, Closures, Exports, Options); arm -> hipe_arm_assemble:assemble(CompiledCode, Closures, Exports, Options); x86 -> hipe_x86_assemble:assemble(CompiledCode, Closures, Exports, Options); amd64 -> hipe_amd64_assemble:assemble(CompiledCode, Closures, Exports, Options); Arch -> ?EXIT({executing_on_an_unsupported_architecture,Arch}) end.%% --------------------------------------------------------------------%% Initialise host and target architectures. Target defaults to host,%% but can be overridden by passing an option {target, Target}.set_architecture(Options) -> put(hipe_host_arch, erlang:system_info(hipe_architecture)), put(hipe_target_arch, proplists:get_value(target, Options, get(hipe_host_arch))), ok.%% This sets up some globally accessed stuff that are needed by the%% compiler process before it even gets the full list of options.%% Therefore, this expands the current set of options for local use.pre_init(Opts) -> Options = expand_options(Opts), %% Initialise some counters used for measurements and benchmarking. If %% the option 'measure_regalloc' is given the compilation will return %% a keylist with the counter values. put(hipe_time, case proplists:get_value(time, Options, false) of true -> [hipe,hipe_main]; OptTime -> OptTime end), [?set_hipe_timer_val(Timer,0) || Timer <- hipe_timers()], [case Counter of {CounterName,InitVal} -> put(CounterName, InitVal); CounterName -> put(CounterName, 0) end || Counter <- proplists:get_value(counters, Options, [])], put(hipe_debug, proplists:get_bool(debug, Options)), put(hipe_inline_fp, proplists:get_bool(inline_fp, Options)), ok.%% Prepare the compiler process by setting up variables which are%% accessed globally. Options have been fully expanded at ths point.init(_Options) -> put(callersavetime,0), put(totalspill,{0,0}), put(spilledtemps,0), put(pre_ra_instrs,0), put(post_ra_instrs,0), put(pre_ra_temps,0), put(post_ra_temps,0), put(noregs,0), put(bbs,0), ok.%% --------------------------------------------------------------------post(Res, Icode, Options) -> TimerVals = case proplists:get_value(timers,Options) of Timers when is_list(Timers) -> [{Timer, ?get_hipe_timer_val(Timer)} || Timer <- Timers]; _ -> [] end, CounterVals = case proplists:get_value(counters,Options) of Counters when is_list(Counters) -> [case Counter of {CounterName, _InitVal} -> {CounterName, get(CounterName)}; CounterName -> {CounterName, get(CounterName)} end || Counter <- Counters]; _ -> [] end, Measures = case proplists:get_bool(measure_regalloc, Options) of true -> get(); % return whole process dictionary list (simplest way...) false -> [] end, Info = TimerVals ++ CounterVals ++ Measures, case proplists:get_bool(get_called_modules, Options) of true -> CalledMods = hipe_icode_callgraph:get_called_modules(Icode), case Info of [] -> {Res, {called_modules, CalledMods}}; _ -> {Res, {info, Info}, {called_modules, CalledMods}} end; false -> case Info of [] -> Res; _ -> {Res, {info, Info}} end end.%% --------------------------------------------------------------------%% @spec version() -> string()%% @doc Returns the current HiPE version as a string().version() -> ?VERSION_STRING().%% ____________________________________________________________________%% %% D O C U M E N T A T I O N - H E L P %%%% @spec () -> ok%% @doc Prints on-line documentation to the standard output.help() -> M = "The HiPE Compiler (Version " ++ ?VERSION_STRING() ++ ")\n" ++ "\n" ++ " The normal way to native-compile Erlang code using HiPE is to\n" ++ " include `native' in the Erlang compiler options, as in:\n" ++ " 1> c(my_module, [native]).\n" ++ " Options to the HiPE compiler must then be passed as follows:\n" ++ " 1> c(my_module, [native,{hipe,Options}]).\n" ++ " Use `help_options()' for details.\n" ++ "\n" ++ " Utility functions:\n" ++ " help()\n" ++ " Prints this message.\n" ++ " help_options()\n" ++ " Prints a description of options recognized by the\n" ++ " HiPE compiler.\n" ++ " help_option(Option)\n" ++ " Prints a description of that option.\n" ++ " help_debug_options()\n" ++ " Prints a description of debug options.\n" ++ " version() ->\n" ++ " Returns the HiPE version as a string'.\n" ++ "\n" ++ " For HiPE developers only:\n" ++ " Use `help_hiper()' for information about HiPE's low-level interface\n", io:put_chars(M), ok.help_hiper() -> M = " This interface is supposed to be used by HiPE-developers only!\n" ++ " Note that all options are specific to the HiPE compiler.\n" ++ " c(Name,Options)\n" ++ " Compiles the module or function Name and loads it\n" ++ " to memory. Name is an atom or a tuple {M,F,A}.\n" ++ " c(Name)\n" ++ " As above, but using only default options.\n" ++ " f(File,Options)\n" ++ " As c(Name,File,Options), but taking the module name\n" ++ " from File.\n" ++ " f(File)\n" ++ " As above, but using only default options.\n" ++ " compile(Name,Options)\n" ++ " Compiles the module or function Name to a binary.\n" ++ " By default, this does not load to memory.\n" ++ " compile(Name)\n" ++ " As above, but using only default options.\n" ++ " file(File,Options)\n" ++ " As compile(Name,File,Options), but taking the\n" ++ " module name from File.\n" ++ " file(File)\n" ++ " As above, but using only default options.\n" ++ " load(Module)\n" ++ " Loads the named module into memory.\n", io:put_chars(M), ok.%% TODO: it should be possible to specify the target somehow when asking%% for available options. Right now, you only see host machine options.%% @spec () -> ok%% @doc Prints documentation about options to the standard output.help_options() -> set_architecture([]), %% needed for target-specific option expansion O1 = expand_options([o1]), O2 = expand_options([o2]), O3 = expand_options([o3]), io:format("HiPE Compiler Options\n" ++ " Boolean-valued options generally have corresponding " ++ "aliases `no_...',\n" ++ " and can also be specified as `{Option, true}' " ++ "or `{Option, false}.\n\n" ++ " General boolean options:\n" ++ " ~p.\n\n" ++ " Non-boolean options:\n" ++ " {'O', Level}, where 0 =< Level =< 3:\n" ++ " Select optimization level (the default is 2).\n\n" ++ " Further options can be found below; " ++ "use `hipe:help_option(Name)' for details.\n\n" ++ " Aliases:\n" ++ " pp_all = ~p,\n" ++ " pp_sparc = pp_native,\n" ++ " pp_x86 = pp_native,\n" ++ " pp_amd64 = pp_native,\n" ++ " pp_ppc = pp_native,\n" ++ " o0 = {'O',0},\n" ++ " o1 = {'O',1} = ~p,\n" ++ " o2 = {'O',2} = ~p ++ o1,\n" ++ " o3 = {'O',3} = ~p ++ o2.\n", [ordsets:from_list([verbose, debug, time, load, pp_beam, pp_icode, pp_rtl, pp_native, pp_asm, timeout]), expand_options([pp_all]), O1 -- [{'O',1}], (O2 -- O1) -- [{'O',2}], (O3 -- O2) -- [{'O',3}]]), ok.%% Documentation of the individual options.%% If you add an option, please add help-text here.option_text('O') -> "Specify optimization level. Used as {'O', LEVEL}.\n" ++ " At the moment levels 0 - 3 are implemented.\n" ++ " Aliases: o1, o2, o3, 'O1', 'O2', O3'.";option_text(debug) -> "Outputs internal debugging information during compilation";option_text(fill_delayslot) -> "Try to optimize Sparc delay slots";option_text(icode_ssa_check) -> "Checks whether Icode is on SSA form or not\n";option_text(icode_ssa_copy_prop) -> "Performs copy propagation on Icode SSA";option_text(icode_ssa_const_prop) -> "Performs sparse conditional constant propagation on Icode SSA";option_text(icode_ssa_struct_reuse) -> "Factors out common structure and list constructions on Icode SSA";option_text(load) -> "Automatically load the produced code into memory";option_text(peephole) -> "Enables peephole optimizations";option_text(pmatch) -> "Enables pattern matching compilation when compiling from Core; " ++ "has no effect when compiling from BEAM bytecode";option_text(pp_asm) -> "Displays assembly listing with addresses and bytecode\n" ++ "Currently available for x86 only";option_text(pp_beam) -> "Display the input BEAM code";option_text(pp_icode) -> "Display the intermediate HiPE-ICode";option_text(pp_rtl) -> "Display the intermediate HiPE-RTL code";option_text(pp_rtl_lcm) -> "Display the intermediate HiPE-RTL lazy code motion sets";
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?