aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/rtl/hipe_rtl_symbolic.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/rtl/hipe_rtl_symbolic.erl')
-rw-r--r--lib/hipe/rtl/hipe_rtl_symbolic.erl99
1 files changed, 99 insertions, 0 deletions
diff --git a/lib/hipe/rtl/hipe_rtl_symbolic.erl b/lib/hipe/rtl/hipe_rtl_symbolic.erl
new file mode 100644
index 0000000000..bc8640dec9
--- /dev/null
+++ b/lib/hipe/rtl/hipe_rtl_symbolic.erl
@@ -0,0 +1,99 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-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%
+%%
+%%-------------------------------------------------------------------
+%% File : hipe_rtl_symbolic.erl
+%% Author : Per Gustafsson <[email protected]>
+%% Description : Expansion of symbolic instructions.
+%%
+%% Created : 18 May 2004 by Per Gustafsson <[email protected]>
+%%-------------------------------------------------------------------
+
+-module(hipe_rtl_symbolic).
+
+-export([expand/1]).
+
+-include("hipe_rtl.hrl").
+-include("hipe_literals.hrl").
+-include("../icode/hipe_icode_primops.hrl").
+
+expand(Cfg) ->
+ Linear = hipe_rtl_cfg:linearize(Cfg),
+ Code = hipe_rtl:rtl_code(Linear),
+ NonFlatCode = [expand_instr(Instr) || Instr <- Code],
+ NewCode = lists:flatten(NonFlatCode),
+ Linear1 = hipe_rtl:rtl_code_update(Linear, NewCode),
+ hipe_rtl_cfg:init(Linear1).
+
+expand_instr(Instr) ->
+ case Instr of
+ #fixnumop{} ->
+ expand_fixnumop(Instr);
+ #gctest{} ->
+ expand_gctest(Instr);
+ _ ->
+ Instr
+ end.
+
+expand_fixnumop(Instr) ->
+ case hipe_rtl:fixnumop_type(Instr) of
+ untag ->
+ Dst = hipe_rtl:fixnumop_dst(Instr),
+ Src = hipe_rtl:fixnumop_src(Instr),
+ hipe_tagscheme:realuntag_fixnum(Dst, Src);
+ tag ->
+ Dst = hipe_rtl:fixnumop_dst(Instr),
+ Src = hipe_rtl:fixnumop_src(Instr),
+ hipe_tagscheme:realtag_fixnum(Dst, Src)
+ end.
+
+expand_gctest(Instr) ->
+ HeapNeed = hipe_rtl:gctest_words(Instr),
+ {GetHPInsn, HP, _PutHPInsn} = hipe_rtl_arch:heap_pointer(),
+ {GetHLIMITInsn, H_LIMIT} = hipe_rtl_arch:heap_limit(),
+ ContLabel = hipe_rtl:mk_new_label(),
+ GCLabel = hipe_rtl:mk_new_label(),
+ ContLabelName = hipe_rtl:label_name(ContLabel),
+ GCLabelName = hipe_rtl:label_name(GCLabel),
+ Tmp = hipe_rtl:mk_new_reg(), % diff between two gc-unsafe pointers
+ StartCode =
+ [GetHPInsn,
+ GetHLIMITInsn,
+ hipe_rtl:mk_alu(Tmp, H_LIMIT, 'sub', HP)],
+ {SeparateCode, GCAmount, HPAmount} =
+ case hipe_rtl:is_reg(HeapNeed) of
+ true ->
+ GA = hipe_rtl:mk_new_reg_gcsafe(),
+ HA = hipe_rtl:mk_new_reg_gcsafe(),
+ {[hipe_rtl:mk_alu(HA, HeapNeed, sll,
+ hipe_rtl:mk_imm(hipe_rtl_arch:log2_word_size()))|
+ hipe_tagscheme:realtag_fixnum(GA, HeapNeed)], GA, HA};
+ false ->
+ WordsNeeded = hipe_rtl:imm_value(HeapNeed),
+ GA = hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(WordsNeeded)),
+ HA = hipe_rtl:mk_imm(WordsNeeded*hipe_rtl_arch:word_size()),
+ {[], GA, HA}
+ end,
+ EndCode =
+ [hipe_rtl:mk_branch(Tmp, 'lt', HPAmount, GCLabelName, ContLabelName, 0.01),
+ GCLabel,
+ hipe_rtl:mk_call([], 'gc_1', [GCAmount], ContLabelName, [], not_remote),
+ ContLabel],
+ StartCode ++ SeparateCode ++ EndCode.
+