1%% -*- erlang-indent-level: 2 -*- 2%% 3%% Licensed under the Apache License, Version 2.0 (the "License"); 4%% you may not use this file except in compliance with the License. 5%% You may obtain a copy of the License at 6%% 7%% http://www.apache.org/licenses/LICENSE-2.0 8%% 9%% Unless required by applicable law or agreed to in writing, software 10%% distributed under the License is distributed on an "AS IS" BASIS, 11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%% See the License for the specific language governing permissions and 13%% limitations under the License. 14 15-ifdef(HIPE_AMD64). 16-define(HIPE_X86_SPECIFIC, hipe_amd64_specific). 17-define(HIPE_X86_RA_POSTCONDITIONS, hipe_amd64_ra_postconditions). 18-define(HIPE_X86_REGISTERS, hipe_amd64_registers). 19-define(HIPE_X86_LIVENESS, hipe_amd64_liveness). 20-define(HIPE_X86_DEFUSE, hipe_amd64_defuse). 21-define(HIPE_X86_SUBST, hipe_amd64_subst). 22-else. 23-define(HIPE_X86_SPECIFIC, hipe_x86_specific). 24-define(HIPE_X86_RA_POSTCONDITIONS, hipe_x86_ra_postconditions). 25-define(HIPE_X86_REGISTERS, hipe_x86_registers). 26-define(HIPE_X86_LIVENESS, hipe_x86_liveness). 27-define(HIPE_X86_DEFUSE, hipe_x86_defuse). 28-define(HIPE_X86_SUBST, hipe_x86_subst). 29-endif. 30 31-module(?HIPE_X86_SPECIFIC). 32 33-export([number_of_temporaries/2]). 34 35%% The following exports are used as M:F(...) calls from other modules; 36%% e.g. hipe_x86_ra_ls. 37-export([analyze/2, 38 bb/3, 39 args/2, 40 labels/2, 41 livein/3, 42 liveout/3, 43 uses/2, 44 defines/2, 45 defines_all_alloc/2, 46 def_use/2, 47 is_arg/2, % used by hipe_ls_regalloc 48 is_move/2, 49 is_spill_move/2, 50 is_fixed/2, % used by hipe_graph_coloring_regalloc 51 is_global/2, 52 is_precoloured/2, 53 reg_nr/2, 54 non_alloc/2, 55 allocatable/1, 56 physical_name/2, 57 all_precoloured/1, 58 new_spill_index/2, % used by hipe_ls_regalloc 59 var_range/2, 60 breadthorder/2, 61 postorder/2, 62 reverse_postorder/2]). 63 64%% callbacks for hipe_regalloc_loop 65-export([check_and_rewrite/3]). 66 67%% callbacks for hipe_regalloc_prepass, hipe_range_split 68-export([mk_move/3, 69 mk_goto/2, 70 redirect_jmp/4, 71 new_label/1, 72 new_reg_nr/1, 73 update_reg_nr/3, 74 update_bb/4, 75 subst_temps/3]). 76 77%% callbacks for hipe_bb_weights 78-export([branch_preds/2]). 79 80check_and_rewrite(CFG, Coloring, _) -> 81 ?HIPE_X86_RA_POSTCONDITIONS:check_and_rewrite(CFG, Coloring, 'normal'). 82 83reverse_postorder(CFG, _) -> 84 hipe_x86_cfg:reverse_postorder(CFG). 85 86breadthorder(CFG, _) -> 87 hipe_x86_cfg:breadthorder(CFG). 88 89postorder(CFG, _) -> 90 hipe_x86_cfg:postorder(CFG). 91 92%% Globally defined registers for linear scan 93is_global(R, _) -> 94 ?HIPE_X86_REGISTERS:temp1() =:= R orelse 95 ?HIPE_X86_REGISTERS:temp0() =:= R orelse 96 ?HIPE_X86_REGISTERS:is_fixed(R). 97 98is_fixed(R, _) -> 99 ?HIPE_X86_REGISTERS:is_fixed(R). 100 101is_arg(R, _) -> 102 ?HIPE_X86_REGISTERS:is_arg(R). 103 104args(CFG, _) -> 105 ?HIPE_X86_REGISTERS:args(hipe_x86_cfg:arity(CFG)). 106 107non_alloc(CFG, _) -> 108 non_alloc_1(?HIPE_X86_REGISTERS:nr_args(), hipe_x86_cfg:params(CFG)). 109 110%% same as hipe_x86_frame:fix_formals/2 111non_alloc_1(0, Rest) -> Rest; 112non_alloc_1(N, [_|Rest]) -> non_alloc_1(N-1, Rest); 113non_alloc_1(_, []) -> []. 114 115%% Liveness stuff 116 117analyze(CFG, _) -> 118 ?HIPE_X86_LIVENESS:analyze(CFG). 119 120livein(Liveness,L,_) -> 121 [X || X <- ?HIPE_X86_LIVENESS:livein(Liveness,L), 122 hipe_x86:temp_is_allocatable(X), 123 hipe_x86:temp_reg(X) =/= ?HIPE_X86_REGISTERS:fcalls(), 124 hipe_x86:temp_reg(X) =/= ?HIPE_X86_REGISTERS:heap_limit(), 125 hipe_x86:temp_type(X) =/= 'double']. 126 127liveout(BB_in_out_liveness,Label,_) -> 128 [X || X <- ?HIPE_X86_LIVENESS:liveout(BB_in_out_liveness,Label), 129 hipe_x86:temp_is_allocatable(X), 130 hipe_x86:temp_reg(X) =/= ?HIPE_X86_REGISTERS:fcalls(), 131 hipe_x86:temp_reg(X) =/= ?HIPE_X86_REGISTERS:heap_limit(), 132 hipe_x86:temp_type(X) =/= 'double']. 133 134%% Registers stuff 135 136allocatable(_) -> 137 ?HIPE_X86_REGISTERS:allocatable(). 138 139all_precoloured(_) -> 140 ?HIPE_X86_REGISTERS:all_precoloured(). 141 142is_precoloured(Reg,_) -> 143 ?HIPE_X86_REGISTERS:is_precoloured(Reg). 144 145physical_name(Reg,_) -> 146 Reg. 147 148%% CFG stuff 149 150labels(CFG,_) -> 151 hipe_x86_cfg:labels(CFG). 152 153var_range(_CFG,_) -> 154 hipe_gensym:var_range(x86). 155 156number_of_temporaries(_CFG,_) -> 157 Highest_temporary = hipe_gensym:get_var(x86), 158 %% Since we can have temps from 0 to Max adjust by +1. 159 Highest_temporary + 1. 160 161bb(CFG,L,_) -> 162 hipe_x86_cfg:bb(CFG,L). 163 164update_bb(CFG,L,BB,_) -> 165 hipe_x86_cfg:bb_add(CFG,L,BB). 166 167branch_preds(Instr,_) -> 168 hipe_x86_cfg:branch_preds(Instr). 169 170%% X86 stuff 171 172def_use(Instruction,_) -> 173 {[X || X <- ?HIPE_X86_DEFUSE:insn_def(Instruction), 174 hipe_x86:temp_is_allocatable(X), 175 hipe_x86:temp_type(X) =/= 'double'], 176 [X || X <- ?HIPE_X86_DEFUSE:insn_use(Instruction), 177 hipe_x86:temp_is_allocatable(X), 178 hipe_x86:temp_type(X) =/= 'double'] 179 }. 180 181uses(I,_) -> 182 [X || X <- ?HIPE_X86_DEFUSE:insn_use(I), 183 hipe_x86:temp_is_allocatable(X), 184 hipe_x86:temp_type(X) =/= 'double']. 185 186defines(I,_) -> 187 [X || X <- ?HIPE_X86_DEFUSE:insn_def(I), 188 hipe_x86:temp_is_allocatable(X), 189 hipe_x86:temp_type(X) =/= 'double']. 190 191defines_all_alloc(I,_) -> ?HIPE_X86_DEFUSE:insn_defs_all(I). 192 193is_move(Instruction,_) -> 194 case hipe_x86:is_move(Instruction) of 195 true -> 196 Src = hipe_x86:move_src(Instruction), 197 Dst = hipe_x86:move_dst(Instruction), 198 case hipe_x86:is_temp(Src) of 199 true -> 200 case hipe_x86:temp_is_allocatable(Src) of 201 true -> 202 case hipe_x86:is_temp(Dst) of 203 true -> 204 hipe_x86:temp_is_allocatable(Dst); 205 false -> false 206 end; 207 false -> false 208 end; 209 false -> false 210 end; 211 false -> false 212 end. 213 214is_spill_move(Instruction,_) -> 215 hipe_x86:is_pseudo_spill_move(Instruction). 216 217reg_nr(Reg,_) -> 218 hipe_x86:temp_reg(Reg). 219 220mk_move(Src, Dst, _) -> 221 hipe_x86:mk_move(Src, Dst). 222 223mk_goto(Label, _) -> 224 hipe_x86:mk_jmp_label(Label). 225 226redirect_jmp(Jmp, ToOld, ToNew, _) when is_integer(ToOld), is_integer(ToNew) -> 227 Ref = make_ref(), 228 put(Ref, false), 229 I = hipe_x86_subst:insn_lbls( 230 fun(Tgt) -> 231 if Tgt =:= ToOld -> put(Ref, true), ToNew; 232 is_integer(Tgt) -> Tgt 233 end 234 end, Jmp), 235 true = erase(Ref), % Assert that something was rewritten 236 I. 237 238new_label(_) -> 239 hipe_gensym:get_next_label(x86). 240 241new_reg_nr(_) -> 242 hipe_gensym:get_next_var(x86). 243 244update_reg_nr(Nr, Temp, _) -> 245 hipe_x86:mk_temp(Nr, hipe_x86:temp_type(Temp)). 246 247subst_temps(SubstFun, Instr, _) -> 248 ?HIPE_X86_SUBST:insn_temps( 249 fun(Op) -> 250 case hipe_x86:temp_is_allocatable(Op) 251 andalso hipe_x86:temp_type(Op) =/= 'double' 252 of 253 true -> SubstFun(Op); 254 false -> Op 255 end 256 end, Instr). 257 258new_spill_index(SpillIndex, _) when is_integer(SpillIndex) -> 259 SpillIndex+1. 260