%% -*- 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 <pergu@it.uu.se> %% Description : Expansion of symbolic instructions. %% %% Created : 18 May 2004 by Per Gustafsson <pergu@it.uu.se> %%------------------------------------------------------------------- -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.