aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/icode/hipe_icode_pp.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/hipe/icode/hipe_icode_pp.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/hipe/icode/hipe_icode_pp.erl')
-rwxr-xr-xlib/hipe/icode/hipe_icode_pp.erl303
1 files changed, 303 insertions, 0 deletions
diff --git a/lib/hipe/icode/hipe_icode_pp.erl b/lib/hipe/icode/hipe_icode_pp.erl
new file mode 100755
index 0000000000..575bbfe43d
--- /dev/null
+++ b/lib/hipe/icode/hipe_icode_pp.erl
@@ -0,0 +1,303 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. 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%
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Copyright (c) 2003 by Erik Stenman.
+%% ====================================================================
+%% Filename : hipe_icode_pp.erl
+%% Module : hipe_icode_pp
+%% Purpose : Pretty-printer for Icode.
+%% Notes :
+%% History : * 2003-04-16 ([email protected]): Created.
+%% CVS :
+%% $Author$
+%% $Date$
+%% $Revision$
+%% ====================================================================
+%%
+%% @doc
+%% Icode Pretty-Printer.
+%% @end
+%%
+%% ====================================================================
+
+-module(hipe_icode_pp).
+
+-export([pp/1, pp/2, pp_block/1]).
+
+-ifdef(DEBUG_ICODE).
+-export([pp_instrs/2]).
+-endif.
+
+-include("hipe_icode.hrl").
+
+%%---------------------------------------------------------------------
+
+-spec pp(#icode{}) -> 'ok'.
+%% @doc Prettyprints linear Icode on stdout.
+%% <p> Badly formed or unknown instructions are printed surrounded
+%% by three stars "***".</p>
+pp(Icode) ->
+ pp(standard_io, Icode).
+
+-spec pp(io:device(), #icode{}) -> 'ok'.
+%% @doc Prettyprints linear Icode on IoDevice.
+%% <p> Badly formed or unknown instructions are printed surrounded by
+%% three stars "***".</p>
+pp(Dev, Icode) ->
+ {Mod, Fun, Arity} = hipe_icode:icode_fun(Icode),
+ Args = hipe_icode:icode_params(Icode),
+ io:format(Dev, "~w:~w/~w(", [Mod, Fun, Arity]),
+ pp_args(Dev, Args),
+ io:format(Dev, ") ->~n", []),
+ io:format(Dev, "%% Info:~p\n",
+ [[case hipe_icode:icode_is_closure(Icode) of
+ true -> 'Closure';
+ false -> 'Not a closure'
+ end,
+ case hipe_icode:icode_is_leaf(Icode) of
+ true -> 'Leaf function';
+ false -> 'Not a leaf function'
+ end |
+ hipe_icode:icode_info(Icode)]]),
+ pp_instrs(Dev, hipe_icode:icode_code(Icode)),
+ io:format(Dev, "%% Data:\n", []),
+ hipe_data_pp:pp(Dev, hipe_icode:icode_data(Icode), icode, "").
+
+-spec pp_block(icode_instrs()) -> 'ok'.
+pp_block(Code) ->
+ pp_instrs(standard_io, Code).
+
+-spec pp_instrs(io:device(), icode_instrs()) -> 'ok'.
+%% @doc Prettyprints a list of Icode instructions.
+pp_instrs(Dev, Is) ->
+ lists:foreach(fun (I) -> pp_instr(Dev, I) end, Is).
+
+%%---------------------------------------------------------------------
+
+pp_instr(Dev, I) ->
+ case I of
+ #icode_label{} ->
+ io:format(Dev, "~p:~n", [hipe_icode:label_name(I)]);
+ #icode_comment{} ->
+ Txt = hipe_icode:comment_text(I),
+ Str = case io_lib:deep_char_list(Txt) of
+ true -> Txt;
+ false -> io_lib:format("~p", [Txt])
+ end,
+ io:format(Dev, " % ~s~n", [Str]);
+ #icode_phi{} ->
+ io:format(Dev, " ", []),
+ pp_arg(Dev, hipe_icode:phi_dst(I)),
+ io:format(Dev, " := phi(", []),
+ pp_phi_args(Dev, hipe_icode:phi_arglist(I)),
+ io:format(Dev, ")~n", []);
+ #icode_move{} ->
+ io:format(Dev, " ", []),
+ pp_arg(Dev, hipe_icode:move_dst(I)),
+ io:format(Dev, " := ", []),
+ pp_arg(Dev, hipe_icode:move_src(I)),
+ io:format(Dev, "~n", []);
+ #icode_call{} ->
+ io:format(Dev, " ", []),
+ case hipe_icode:call_dstlist(I) of
+ [] -> %% result is unused -- e.g. taken out by dead code elimination
+ io:format(Dev, "_ := ", []);
+ DstList ->
+ pp_args(Dev, DstList),
+ io:format(Dev, " := ", [])
+ end,
+ pp_fun(Dev, hipe_icode:call_fun(I),
+ hipe_icode:call_args(I),
+ hipe_icode:call_type(I),
+ hipe_icode:call_in_guard(I)),
+ case hipe_icode:call_continuation(I) of
+ [] ->
+ ok;
+ CC ->
+ io:format(Dev, " -> ~w", [CC])
+ end,
+ case hipe_icode:call_fail_label(I) of
+ [] -> io:format(Dev, "~n", []);
+ Fail -> io:format(Dev, ", #fail ~w~n", [Fail])
+ end;
+ #icode_enter{} ->
+ io:format(Dev, " ", []),
+ pp_fun(Dev, hipe_icode:enter_fun(I),
+ hipe_icode:enter_args(I),
+ hipe_icode:enter_type(I)),
+ io:format(Dev, "~n", []);
+ #icode_return{} ->
+ io:format(Dev, " return(", []),
+ pp_args(Dev, hipe_icode:return_vars(I)),
+ io:format(Dev, ")~n", []);
+ #icode_begin_try{} ->
+ io:format(Dev, " begin_try -> ~w cont ~w~n",
+ [hipe_icode:begin_try_label(I),
+ hipe_icode:begin_try_successor(I)]);
+ #icode_begin_handler{} ->
+ io:format(Dev, " ", []),
+ pp_args(Dev, hipe_icode:begin_handler_dstlist(I)),
+ io:format(Dev, " := begin_handler()~n",[]);
+ #icode_end_try{} ->
+ io:format(Dev, " end_try~n", []);
+ #icode_fail{} ->
+ Type = hipe_icode:fail_class(I),
+ io:format(Dev, " fail(~w, [", [Type]),
+ pp_args(Dev, hipe_icode:fail_args(I)),
+ case hipe_icode:fail_label(I) of
+ [] -> io:put_chars(Dev, "])\n");
+ Fail -> io:format(Dev, "]) -> ~w\n", [Fail])
+ end;
+ #icode_if{} ->
+ io:format(Dev, " if ~w(", [hipe_icode:if_op(I)]),
+ pp_args(Dev, hipe_icode:if_args(I)),
+ io:format(Dev, ") then ~p (~.2f) else ~p~n",
+ [hipe_icode:if_true_label(I), hipe_icode:if_pred(I),
+ hipe_icode:if_false_label(I)]);
+ #icode_switch_val{} ->
+ io:format(Dev, " switch_val ",[]),
+ pp_arg(Dev, hipe_icode:switch_val_term(I)),
+ pp_switch_cases(Dev, hipe_icode:switch_val_cases(I)),
+ io:format(Dev, " fail -> ~w\n",
+ [hipe_icode:switch_val_fail_label(I)]);
+ #icode_switch_tuple_arity{} ->
+ io:format(Dev, " switch_tuple_arity ",[]),
+ pp_arg(Dev, hipe_icode:switch_tuple_arity_term(I)),
+ pp_switch_cases(Dev,hipe_icode:switch_tuple_arity_cases(I)),
+ io:format(Dev, " fail -> ~w\n",
+ [hipe_icode:switch_tuple_arity_fail_label(I)]);
+ #icode_type{} ->
+ io:format(Dev, " if is_", []),
+ pp_type(Dev, hipe_icode:type_test(I)),
+ io:format(Dev, "(", []),
+ pp_args(Dev, hipe_icode:type_args(I)),
+ io:format(Dev, ") then ~p (~.2f) else ~p~n",
+ [hipe_icode:type_true_label(I), hipe_icode:type_pred(I),
+ hipe_icode:type_false_label(I)]);
+ #icode_goto{} ->
+ io:format(Dev, " goto ~p~n", [hipe_icode:goto_label(I)])
+ end.
+
+pp_fun(Dev, Fun, Args, Type) ->
+ pp_fun(Dev, Fun, Args, Type, false).
+
+pp_fun(Dev, Fun, Args, Type, Guard) ->
+ case Type of
+ primop ->
+ hipe_icode_primops:pp(Dev, Fun);
+ local ->
+ {_,F,A} = Fun,
+ io:format(Dev, "~w/~w", [F, A]);
+ remote ->
+ {M,F,A} = Fun,
+ io:format(Dev, "~w:~w/~w", [M, F, A])
+ end,
+ io:format(Dev, "(", []),
+ pp_args(Dev, Args),
+ case Guard of
+ true ->
+ case Type of
+ primop ->
+ io:format(Dev, ") (primop,guard)", []);
+ _ ->
+ io:format(Dev, ") (guard)", [])
+ end;
+ false ->
+ case Type of
+ primop ->
+ io:format(Dev, ") (primop)", []);
+ _ ->
+ io:format(Dev, ")", [])
+ end
+ end.
+
+pp_arg(Dev, Arg) ->
+ case hipe_icode:is_variable(Arg) of
+ true ->
+ case hipe_icode:is_var(Arg) of
+ true ->
+ N = hipe_icode:var_name(Arg),
+ io:format(Dev, "v~p", [N]);
+ false ->
+ case hipe_icode:is_reg(Arg) of
+ true ->
+ N = hipe_icode:reg_name(Arg),
+ io:format(Dev, "r~p", [N]);
+ false ->
+ N = hipe_icode:fvar_name(Arg),
+ io:format(Dev, "fv~p", [N])
+ end
+ end,
+ case hipe_icode:is_annotated_variable(Arg) of
+ true ->
+ {_,Val,Fun} = hipe_icode:variable_annotation(Arg),
+ io:format(Dev, " (~s)", [Fun(Val)]);
+ false ->
+ ok
+ end;
+ false ->
+ Const = hipe_icode:const_value(Arg),
+ io:format(Dev, "~p", [Const]) % ~p because it also prints ""
+ end.
+
+pp_args(_Dev, []) -> ok;
+pp_args(Dev, [A]) ->
+ pp_arg(Dev, A);
+pp_args(Dev, [A|Args]) ->
+ pp_arg(Dev, A),
+ io:format(Dev, ", ", []),
+ pp_args(Dev, Args).
+
+pp_phi_args(_Dev, []) -> ok;
+pp_phi_args(Dev, [{Pred,A}]) ->
+ io:format(Dev, "{~w, ", [Pred]),
+ pp_arg(Dev, A),
+ io:format(Dev, "}", []);
+pp_phi_args(Dev, [{Pred,A}|Args]) ->
+ io:format(Dev, "{~w, ", [Pred]),
+ pp_arg(Dev, A),
+ io:format(Dev, "}, ", []),
+ pp_phi_args(Dev, Args).
+
+pp_type(Dev, T) ->
+ io:format(Dev, "~w", [T]).
+
+pp_switch_cases(Dev, Cases) ->
+ io:format(Dev, " of\n",[]),
+ pp_switch_cases(Dev, Cases,1),
+ io:format(Dev, "",[]).
+
+pp_switch_cases(Dev, [{Val,L}], _Pos) ->
+ io:format(Dev, " ",[]),
+ pp_arg(Dev, Val),
+ io:format(Dev, " -> ~w\n", [L]);
+pp_switch_cases(Dev, [{Val, L}|Ls], Pos) ->
+ io:format(Dev, " ",[]),
+ pp_arg(Dev, Val),
+ io:format(Dev, " -> ~w;\n", [L]),
+ NewPos = Pos,
+ %% case Pos of
+ %% 5 -> io:format(Dev, "\n ",[]),
+ %% 0;
+ %% N -> N + 1
+ %% end,
+ pp_switch_cases(Dev, Ls, NewPos);
+pp_switch_cases(_Dev, [], _) -> ok.
+