diff options
Diffstat (limited to 'lib/hipe/rtl/hipe_rtl_symbolic.erl')
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_symbolic.erl | 99 |
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. + |