1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
|
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
%% @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/4]).
%%=====================================================================
-ifndef(DEBUG).
-define(DEBUG,1).
-endif.
-define(HIPE_INSTRUMENT_COMPILER, true). %% Turn on instrumentation.
-include("hipe.hrl").
-include("../icode/hipe_icode.hrl").
%%-include("../rtl/hipe_rtl.hrl").
%%=====================================================================
-type comp_icode_ret() :: {'native',hipe_architecture(),{'unprofiled',_}}
| {'rtl',tuple()} | {'llvm_binary',term()}.
%%=====================================================================
%% @spec compile_icode(MFA::mfa(),
%% LinearIcode::#icode{},
%% CompilerOptions::comp_options(),
%% CompServers::#comp_servers()) ->
%% {native,Platform,{unprofiled,NativeCode}} | {rtl,RTLCode}
%%
%% @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>
-spec compile_icode(mfa(), #icode{}, comp_options(), #comp_servers{}) ->
comp_icode_ret().
compile_icode(MFA, LinearIcode, Options, Servers) ->
compile_icode(MFA, LinearIcode, Options, Servers, 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, Servers, DebugState) ->
%% Set up gensym with the right ranges for this function.
{LMin,LMax} = hipe_icode:icode_label_range(LinearIcode0),
hipe_gensym:set_label_range(icode, LMin, LMax+1),
{VMin,VMax} = hipe_icode:icode_var_range(LinearIcode0),
hipe_gensym:set_var_range(icode, VMin, 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(IcodeCfg0),
IcodeCfg1 = icode_handle_exceptions(IcodeCfg0, MFA, Options),
IcodeCfg3 = icode_inline_bifs(IcodeCfg1, Options),
pp(IcodeCfg3, MFA, icode, pp_icode, Options, Servers),
IcodeCfg4 = icode_ssa(IcodeCfg3, MFA, Options, Servers),
IcodeCfg5 = icode_split_arith(IcodeCfg4, MFA, Options),
pp(IcodeCfg5, MFA, icode, pp_icode_split_arith, Options, Servers),
IcodeCfg6 = icode_heap_test(IcodeCfg5, Options),
IcodeCfg7 = icode_remove_trivial_bbs(IcodeCfg6, Options),
pp(IcodeCfg7, MFA, icode, pp_opt_icode, Options, Servers),
pp(IcodeCfg7, MFA, icode_liveness, pp_icode_liveness, Options, Servers),
FinalIcode = hipe_icode_cfg:cfg_to_linear(IcodeCfg7),
?opt_stop_timer("Icode"),
{LinearRTL, Roots} = ?option_time(icode_to_rtl(MFA, FinalIcode, Options, Servers),
"RTL", Options),
case proplists:get_bool(to_rtl, Options) of
false ->
case proplists:get_bool(to_llvm, Options) of
false ->
rtl_to_native(MFA, LinearRTL, Options, DebugState);
true ->
%% The LLVM backend returns binary code, unlike the rest of the HiPE
%% backends which return native assembly.
rtl_to_llvm_to_binary(MFA, LinearRTL, Roots, Options, DebugState)
end;
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).
icode_ssa_binary_pass(IcodeSSA, Options) ->
case proplists:get_bool(binary_opt, Options) of
true ->
?option_time(hipe_icode_bincomp:cfg(IcodeSSA),
"Icode binary pass", Options);
false ->
IcodeSSA
end.
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);
false ->
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).
pp(Cfg, MFA, Level, PrintOption, Options, Servers) ->
perform_io(pp_fun(Cfg, MFA, get_pp_module(Level),
proplists:get_value(PrintOption, Options)),
Servers#comp_servers.pp_server).
pp_fun(Cfg, MFA, PP, PrintOptionValue) ->
case PrintOptionValue of
true ->
fun() -> PP:pp(Cfg) end;
{only, Lst} when is_list(Lst) ->
case lists:member(MFA, Lst) of
true ->
fun() -> PP:pp(Cfg) end;
false ->
no_fun
end;
{only, MFA} ->
fun() -> PP:pp(Cfg) end;
{file, FileName} ->
fun() ->
{ok, File} = file:open(FileName, [write,append]),
PP:pp(File, Cfg),
file:close(File)
end;
_ ->
no_fun
end.
get_pp_module(icode) -> hipe_icode_cfg;
get_pp_module(rtl) -> hipe_rtl_cfg;
get_pp_module(rtl_linear) -> hipe_rtl;
get_pp_module(icode_liveness) -> hipe_icode_liveness;
get_pp_module(rtl_liveness) -> hipe_rtl_liveness.
perform_io(no_fun, _) -> ok;
perform_io(Fun,PPServer) when is_pid(PPServer) ->
PPServer ! {print,Fun};
perform_io(Fun, undefined) ->
Fun().
%%--------------------------------------------------------------------
%%
%% 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, Servers) ->
?opt_start_timer("Icode SSA passes"),
IcodeSSA0 = icode_ssa_convert(IcodeCfg0, Options),
pp(IcodeSSA0, MFA, icode, pp_icode_ssa, Options, Servers),
IcodeSSA1 = icode_ssa_const_prop(IcodeSSA0, Options),
IcodeSSA2 = icode_ssa_dead_code_elimination(IcodeSSA1, Options),
IcodeSSA3 = icode_ssa_copy_prop(IcodeSSA2, Options),
IcodeSSA3a = icode_ssa_binary_pass(IcodeSSA3, Options),
IcodeSSA4 = icode_ssa_type(IcodeSSA3a, MFA, Options, Servers),
IcodeSSA5 = icode_ssa_dead_code_elimination(IcodeSSA4, Options),
IcodeSSA6 = icode_ssa_struct_reuse(IcodeSSA5, Options),
icode_ssa_check(IcodeSSA6, Options), %% just for sanity
pp(IcodeSSA6, MFA, icode, pp_icode_ssa, Options, Servers),
IcodeCfg = icode_ssa_unconvert(IcodeSSA6, Options),
?opt_stop_timer("Icode SSA passes"),
IcodeCfg.
icode_ssa_type(IcodeSSA, MFA, Options, Servers) ->
case proplists:get_value(icode_type, Options) of
false -> IcodeSSA;
undefined -> IcodeSSA;
true ->
AnnIcode1 = icode_ssa_type_info(IcodeSSA, MFA, Options, Servers),
pp(AnnIcode1, MFA, icode, pp_typed_icode, Options, Servers),
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, Servers),
pp(AnnIcode3, MFA, icode, pp_range_icode, Options, Servers),
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: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_bool(icode_ssa_copy_prop, Options) of
true ->
?option_time(hipe_icode_ssa_copy_prop:cfg(IcodeSSA),
"Icode SSA copy propagation", Options);
false ->
IcodeSSA
end.
icode_ssa_struct_reuse(IcodeSSA, Options) ->
case proplists:get_value(icode_ssa_struct_reuse, Options) of
true ->
?option_time(hipe_icode_ssa_struct_reuse:struct_reuse(IcodeSSA),
"Icode SSA structure reuse", Options);
_ ->
IcodeSSA
end.
icode_ssa_type_info(IcodeSSA, MFA, Options, Servers) ->
?option_time(hipe_icode_type:cfg(IcodeSSA, MFA, Options, Servers),
io_lib:format("Icode SSA type info for ~p", [MFA]), Options).
icode_range_analysis(IcodeSSA, MFA, Options, Servers) ->
case proplists:get_bool(icode_range, Options) of
true ->
?option_time(hipe_icode_range:cfg(IcodeSSA, MFA, Options, Servers),
"Icode SSA integer range analysis", Options);
false ->
IcodeSSA
end.
icode_ssa_dead_code_elimination(IcodeSSA, Options) ->
IcodeSSA1 = ?option_time(hipe_icode_ssa:remove_dead_code(IcodeSSA),
"Icode SSA dead code elimination pass 2",
Options),
hipe_icode_cfg:remove_unreachable_code(IcodeSSA1).
icode_ssa_check(IcodeSSA, Options) ->
?when_option(icode_ssa_check, Options,
?option_time(hipe_icode_ssa:check(IcodeSSA),
"Icode check for SSA-ness", Options)).
icode_ssa_unconvert(IcodeSSA, Options) ->
?option_time(hipe_icode_ssa:unconvert(IcodeSSA),
"Icode SSA unconversion", Options).
%%=====================================================================
%%
%% @spec icode_to_rtl(MFA::mfa(), Icode, options()) -> Linear_RTL_code
%% @end
%%=====================================================================
%%---------------------------------------------------------------------
%%
%% The passes on RTL are as follows:
%%
%% 1. The translation to RTL, in particular the way exceptions are
%% currently handled in RTL, introduces some unreachable code.
%% Therefore, unreachable code is removed early on followed by a
%% pass that removes trivial basic blocks so as to have smaller
%% code to play with.
%%
%% 2. Code is then converted to SSA so as to perform as many
%% optimizations as possible in this pass.
%% Currently, the following optimizations are performed on SSA:
%% - sparse conditional constant propagation (controlled by an option)
%% - dead code elimination
%% - detection of available exceptions
%% - partial redundancy elimination (controlled by an option)
%% Finally, code is converted back to non-SSA form.
%%
%% 3. rtl_symbolic expands some symbolic instructions.
%%
%% 4. rtl_lcm performs a lazy code motion on RTL.
%%
%%----------------------------------------------------------------------
icode_to_rtl(MFA, Icode, Options, Servers) ->
debug("ICODE -> RTL: ~w, ~w~n", [MFA, hash(Icode)], Options),
LinearRTL = translate_to_rtl(Icode, Options),
pp(LinearRTL, MFA, rtl_linear, pp_rtl_linear, Options, Servers),
RtlCfg = initialize_rtl_cfg(LinearRTL, Options),
%% hipe_rtl_cfg:pp(RtlCfg),
RtlCfg0 = hipe_rtl_cfg:remove_unreachable_code(RtlCfg),
RtlCfg1 = hipe_rtl_cfg:remove_trivial_bbs(RtlCfg0),
%% hipe_rtl_cfg:pp(RtlCfg1),
RtlCfg2 = rtl_ssa(RtlCfg1, Options),
RtlCfg3 = rtl_symbolic(RtlCfg2, Options),
%% hipe_rtl_cfg:pp(RtlCfg3),
pp(RtlCfg3, MFA, rtl_liveness, pp_rtl_liveness, Options, Servers),
RtlCfg4 = rtl_lcm(RtlCfg3, Options),
%% LLVM: A liveness analysis on RTL must be performed in order to find the GC
%% roots and explicitly mark them (in RTL) when they go out of scope (only
%% when the LLVM backend is used).
{RtlCfg5, Roots} =
case proplists:get_bool(to_llvm, Options) of
false ->
{RtlCfg4, []};
true ->
hipe_llvm_liveness:analyze(RtlCfg4)
end,
pp(RtlCfg5, MFA, rtl, pp_rtl, Options, Servers),
LinearRTL1 = hipe_rtl_cfg:linearize(RtlCfg5),
LinearRTL2 = hipe_rtl_cleanup_const:cleanup(LinearRTL1),
%% hipe_rtl:pp(standard_io, LinearRTL2),
{LinearRTL2, Roots}.
translate_to_rtl(Icode, Options) ->
%% GC tests should have been added in the conversion to Icode.
?option_time(hipe_icode2rtl:translate(Icode, Options),
"translate", Options).
initialize_rtl_cfg(LinearRTL, Options) ->
?option_time(hipe_rtl_cfg:init(LinearRTL), "to cfg", Options).
rtl_symbolic(RtlCfg, Options) ->
?option_time(hipe_rtl_symbolic:expand(RtlCfg),
"Expansion of symbolic instructions", Options).
%%----------------------------------------------------------------------
%%
%% RTL passes on SSA form. The following constraints are applicable:
%%
%% 1. ssa_convert must be first and ssa_unconvert last.
%%
%% 2. dead_code_elimination should be performed after conditional
%% constant propagation in order to cleanup dead code that might
%% be created by that pass.
%%
%% 3. avail_expr ... (PER ADD THIS)
%%
%% 4. rtl_ssapre performs A-SSAPRE and has to be done after all other
%% optimizations.
%%
%% 5. ssa_check could be put in between all passes to make sure that
%% they preserve SSA-ness.
%%
%%----------------------------------------------------------------------
rtl_ssa(RtlCfg0, Options) ->
case proplists:get_bool(rtl_ssa, Options) of
true ->
?opt_start_timer("RTL SSA passes"),
RtlSSA0 = rtl_ssa_convert(RtlCfg0, Options),
RtlSSA1 = rtl_ssa_const_prop(RtlSSA0, Options),
%% RtlSSA1a = rtl_ssa_copy_prop(RtlSSA1, Options),
RtlSSA2 = rtl_ssa_dead_code_elimination(RtlSSA1, Options),
RtlSSA3 = rtl_ssa_avail_expr(RtlSSA2, Options),
RtlSSA4 = rtl_ssapre(RtlSSA3, Options),
%% rtl_ssa_check(RtlSSA4, Options), %% just for sanity
RtlCfg = rtl_ssa_unconvert(RtlSSA4, Options),
case proplists:get_bool(pp_rtl_ssa, Options) of
true ->
io:format("%%------------- After SSA un-conversion -----------\n"),
hipe_rtl_cfg:pp(RtlCfg);
false ->
ok
end,
?opt_stop_timer("RTL SSA passes"),
RtlCfg;
false ->
RtlCfg0
end.
rtl_ssa_convert(RtlCfg, Options) ->
case proplists:get_bool(pp_rtl_ssa, Options) of
true ->
io:format("%%------------- Before SSA conversion --------------\n"),
hipe_rtl_cfg:pp(RtlCfg),
io:format("%%------------- After SSA conversion --------------\n"),
RtlCfgSSA = hipe_rtl_ssa:convert(RtlCfg),
hipe_rtl_cfg:pp(RtlCfgSSA),
io:format("%%------------- SSA check warnings below -----------\n"),
hipe_rtl_ssa:check(RtlCfgSSA),
RtlCfgSSA;
false ->
?option_time(hipe_rtl_ssa:convert(RtlCfg),
"RTL SSA conversion", Options)
end.
rtl_ssa_const_prop(RtlCfgSSA, Options) ->
case proplists:get_bool(rtl_ssa_const_prop, Options) of
true ->
?option_time(hipe_rtl_ssa_const_prop:propagate(RtlCfgSSA),
"RTL SSA sparse conditional constant propagation", Options);
false ->
RtlCfgSSA
end.
rtl_ssa_dead_code_elimination(RtlCfgSSA, Options) ->
?option_time(hipe_rtl_ssa:remove_dead_code(RtlCfgSSA),
"RTL SSA dead code elimination", Options).
rtl_ssa_avail_expr(RtlCfgSSA, Options) ->
?option_time(hipe_rtl_ssa_avail_expr:cfg(RtlCfgSSA),
"RTL SSA heap optimizations", Options).
%%---------------------------------------------------------------------
rtl_ssapre(RtlCfg, Options) ->
case proplists:get_bool(rtl_ssapre, Options) of
true ->
?opt_start_timer("Partial Redundancy Elimination (A-SSAPRE)"),
NewRtlCfg = hipe_rtl_ssapre:rtl_ssapre(RtlCfg, Options),
?opt_stop_timer("Partial Redundancy Elimination (A-SSAPRE)"),
NewRtlCfg;
false ->
RtlCfg
end.
%%---------------------------------------------------------------------
rtl_ssa_unconvert(RtlCfgSSA, Options) ->
?option_time(hipe_rtl_ssa:unconvert(RtlCfgSSA),
"RTL SSA un-convert", Options).
%%---------------------------------------------------------------------
rtl_lcm(RtlCfg, Options) ->
case proplists:get_bool(rtl_lcm, Options) of
true ->
?opt_start_timer("RTL lazy code motion"),
%% ?option_time(hipe_rtl_lcm:rtl_lcm(RtlCfg, Options),
%% "RTL lazy code motion", Options);
RtlCfg1 = hipe_rtl_lcm:rtl_lcm(RtlCfg, Options),
?opt_stop_timer("RTL lazy code motion"),
RtlCfg1;
false ->
RtlCfg
end.
%%=====================================================================
%% Translation to native code takes place in the corresponding back-end
%%=====================================================================
rtl_to_native(MFA, LinearRTL, Options, DebugState) ->
?opt_start_timer("Native code"),
LinearNativeCode =
case get(hipe_target_arch) of
ultrasparc ->
hipe_sparc_main:rtl_to_sparc(MFA, LinearRTL, Options);
powerpc ->
hipe_ppc_main:rtl_to_ppc(MFA, LinearRTL, Options);
ppc64 ->
hipe_ppc_main:rtl_to_ppc(MFA, LinearRTL, Options);
arm ->
hipe_arm_main:rtl_to_arm(MFA, LinearRTL, Options);
x86 ->
hipe_x86_main:rtl_to_x86(MFA, LinearRTL, Options);
amd64 ->
hipe_amd64_main:rtl_to_amd64(MFA, LinearRTL, Options)
end,
?opt_stop_timer("Native code"),
put(hipe_debug, DebugState),
LinearNativeCode.
%% Translate Linear RTL to binary code using LLVM.
rtl_to_llvm_to_binary(MFA, LinearRTL, Roots, Options, DebugState) ->
?opt_start_timer("LLVM native code"),
%% BinaryCode is a tuple, as defined in llvm/hipe_llvm_main module, which
%% contains the binary code together with info needed by the loader, e.g.
%% ConstTab, Refs, LabelMap, etc.
BinaryCode = hipe_llvm_main:rtl_to_native(MFA, LinearRTL, Roots, Options),
?opt_stop_timer("LLVM native code"),
put(hipe_debug, DebugState),
{llvm_binary, BinaryCode}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Debugging stuff ...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
debug(Text, Args, Options) ->
?when_option(debug, Options, ?msg(Text,Args)).
hash(X) ->
erlang:phash(X, 16#7f3f5f1).
|