%% -*- erlang-indent-level: 2 -*-
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Copyright (c) 2001 by Erik Johansson. All Rights Reserved
%% ====================================================================
%% Module : hipe_rtl_varmap
%% Purpose :
%% Notes :
%% History : * 2001-04-10 Erik Johansson ([email protected]): Created.
%% ====================================================================
%% Exports :
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(hipe_rtl_varmap).
-export([init/1,
ivs2rvs/2,
icode_var2rtl_var/2,
icode_label2rtl_label/2]).
%-------------------------------------------------------------------------
-include("../main/hipe.hrl").
-include("../icode/hipe_icode.hrl").
%-------------------------------------------------------------------------
%% @spec init(IcodeRecord::#icode{}) -> {Args, VarMap}
%%
%% @doc Initializes gensym for RTL.
-spec init(#icode{}) -> {[_], _}. % XXX: fix me please
init(IcodeRecord) ->
hipe_gensym:init(rtl),
hipe_gensym:set_var(rtl, hipe_rtl_arch:first_virtual_reg()),
hipe_gensym:set_label(rtl, 0),
VarMap = new_var_map(),
{_Args, _VarMap1} = ivs2rvs(hipe_icode:icode_params(IcodeRecord), VarMap).
%%------------------------------------------------------------------------
%%
%% Mapping of labels and variables from Icode to RTL.
%%
%%------------------------------------------------------------------------
%% @spec icode_label2rtl_label(Icode_Label::term(), LabelMap::term()) ->
%% {RTL_Label, NewLabelMap}
%%
%% @doc Converts an Icode label to an RTL label.
icode_label2rtl_label(LabelName, Map) ->
case lookup(LabelName, Map) of
{value, NewLabel} ->
{NewLabel, Map};
none ->
NewLabel = hipe_rtl:mk_new_label(),
{NewLabel, insert(LabelName, NewLabel, Map)}
end.
%% @spec ivs2rvs(Icode_Vars::[term()], VarMap::term()) -> {[RTL_Var],NewVarMap}
%%
%% @doc Converts a list of Icode variables to a list of RTL variables.
ivs2rvs([], VarMap) ->
{[], VarMap};
ivs2rvs([V|Vs], VarMap) ->
{NewV, VarMap0} = icode_var2rtl_var(V, VarMap),
{NewVs, VarMap1} = ivs2rvs(Vs, VarMap0),
{[NewV|NewVs], VarMap1}.
%% @spec icode_var2rtl_var(Icode_Var::term(), VarMap::term()) ->
%% {RTL_Var, NewVarMap}
%%
%% @doc Converts an Icode variable to an RTL variable.
icode_var2rtl_var(Var, Map) ->
Value = lookup(Var, Map),
case Value of
none ->
case type_of_var(Var) of
fvar ->
NewVar = hipe_rtl:mk_new_fpreg(),
{NewVar, insert(Var, NewVar, Map)};
var ->
NewVar = hipe_rtl:mk_new_var(),
{NewVar, insert(Var, NewVar, Map)};
{reg, IsGcSafe} ->
NewVar =
case IsGcSafe of
true -> hipe_rtl:mk_new_reg_gcsafe();
false -> hipe_rtl:mk_new_reg()
end,
{NewVar, insert(Var, NewVar, Map)}
end;
{value, NewVar} ->
{NewVar, Map}
end.
%%
%% Simple type test
%%
type_of_var(X) ->
case hipe_icode:is_fvar(X) of
true ->
fvar;
false ->
case hipe_icode:is_var(X) of
true ->
var;
false ->
case hipe_icode:is_reg(X) of
true ->
{reg, hipe_icode:reg_is_gcsafe(X)};
false ->
%% Sanity check
case hipe_icode:is_const(X) of
true -> const;
false ->
exit({"Unknown Icode variable", X})
end
end
end
end.
%%
%% Helping utilities
%%
new_var_map() ->
gb_trees:empty().
lookup(V, Map) ->
gb_trees:lookup(V, Map).
insert(Key, Val, Map) ->
gb_trees:insert(Key, Val, Map).