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 + -
显示快捷键?