1
%%% -*- erlang-indent-level: 4 -*-
3
%%% simple local x86 regalloc
5
-module(hipe_x86_ra_dummy).
7
-include("hipe_x86.hrl").
8
-define(HIPE_INSTRUMENT_COMPILER, true). % enable instrumentation
9
-include("../main/hipe.hrl").
11
ra(X86Defun, Coloring_fp, Options) ->
12
#defun{code=Code0} = X86Defun,
13
Code1 = do_insns(Code0),
14
%% Record all pseudos as spilled.
15
%% ?add_spills(Options, hipe_gensym:get_var() -
16
%% hipe_x86_registers:first_virtual()),
17
NofSpilledFloats = count_non_float_spills(Coloring_fp),
18
NofFloats = length(Coloring_fp),
19
?add_spills(Options, hipe_gensym:get_var() -
20
hipe_x86_registers:first_virtual()-
24
{X86Defun#defun{code=Code1,
25
var_range={0, hipe_gensym:get_var()}},
28
count_non_float_spills(Coloring_fp)->
29
count_non_float_spills(Coloring_fp,0).
30
count_non_float_spills([{_,To}|Tail], Num)->
31
case hipe_x86_specific_fp:is_precolored(To) of
33
count_non_float_spills(Tail, Num);
35
count_non_float_spills(Tail, Num+1)
37
count_non_float_spills([],Num) ->
40
do_insns([I|Insns]) ->
41
do_insn(I) ++ do_insns(Insns);
45
do_insn(I) -> % Insn -> Insn list
70
%% comment, jmp*, label, pseudo_call, pseudo_jcc, pseudo_tailcall,
71
%% pseudo_tailcall_prepare, push, ret
78
#alu{src=Src0,dst=Dst0} = I,
79
{FixSrc,Src,FixDst,Dst} = do_binary(Src0, Dst0),
80
FixSrc ++ FixDst ++ [I#alu{src=Src,dst=Dst}].
85
#cmp{src=Src0,dst=Dst0} = I,
86
{FixSrc, Src, FixDst, Dst} = do_binary(Src0, Dst0),
87
FixSrc ++ FixDst ++ [I#cmp{src=Src,dst=Dst}].
89
%%% Fix a jmp_switch op.
92
#jmp_switch{temp=Temp} = I,
93
case temp_is_pseudo(Temp) of
97
Reg = hipe_x86:mk_temp(hipe_x86_registers:temp0(), 'untagged'),
98
[hipe_x86:mk_move(Temp, Reg), I#jmp_switch{temp=Reg}]
105
case temp_is_pseudo(Temp) of
109
Reg = hipe_x86:mk_temp(hipe_x86_registers:temp0(), 'untagged'),
110
[I#lea{temp=Reg}, hipe_x86:mk_move(Reg, Temp)]
116
#move{src=Src0,dst=Dst0} = I,
117
{FixSrc, Src, FixDst, Dst} = do_binary(Src0, Dst0),
118
FixSrc ++ FixDst ++ [I#move{src=Src,dst=Dst}].
123
#movsx{src=Src0,dst=Dst0} ->
124
fix_src_operand(Src0);
125
#movzx{src=Src0,dst=Dst0} ->
126
fix_src_operand(Src0)
128
{FixDst, Dst} = fix_dst_operand(Dst0),
129
Reg = hipe_x86_registers:temp0(),
130
Dst2 = clone(Dst, Reg),
132
case is_mem_opnd(Dst) of
134
Reg = hipe_x86_registers:temp0(),
135
Dst2 = clone(Dst, Reg),
138
[hipe_x86:mk_movsx(Src, Dst2), hipe_x86:mk_move(Dst2, Dst)];
140
[hipe_x86:mk_movzx(Src, Dst2), hipe_x86:mk_move(Dst2, Dst)]
145
[hipe_x86:mk_movsx(Src, Dst)];
147
[hipe_x86:mk_movzx(Src, Dst)]
151
FixSrc ++ FixDst ++ I2.
158
#fmov{src=Src0,dst=Dst0} = I,
159
{FixSrc, Src, FixDst, Dst} = do_binary(Src0, Dst0),
160
FixSrc ++ FixDst ++ [I#fmov{src=Src,dst=Dst}].
163
#shift{src=Src0,dst=Dst0} = I,
164
{FixDst, Dst} = fix_dst_operand(Dst0),
165
Reg = hipe_x86_registers:ecx(),
168
FixDst ++ [I#shift{dst=Dst}];
169
#x86_temp{reg=Reg} ->
170
FixDst ++ [I#shift{dst=Dst}]
173
%%% Fix the operands of a binary op.
174
%%% 1. remove pseudos from any explicit memory operands
175
%%% 2. if both operands are (implicit or explicit) memory operands,
176
%%% move src to a reg and use reg as src in the original insn
178
do_binary(Src0, Dst0) ->
179
{FixSrc, Src} = fix_src_operand(Src0),
180
{FixDst, Dst} = fix_dst_operand(Dst0),
182
case is_mem_opnd(Src) of
186
case is_mem_opnd(Dst) of
190
Reg = hipe_x86_registers:temp0(),
191
Src2 = clone(Src, Reg),
192
FixSrc2 = FixSrc ++ [hipe_x86:mk_move(Src, Src2)],
196
{FixSrc3, Src3, FixDst, Dst}.
198
%%% Fix any x86_mem operand to not refer to any pseudos.
199
%%% The fixup may use additional instructions and registers.
200
%%% 'src' operands may clobber '%temp0'.
201
%%% 'dst' operands may clobber '%temp1'.
202
%%% (This is not arbitrary. The translation of restore_catch does a
203
%%% "move %eax,<dst>", and fail_to does a "move <src>,%eax".)
205
fix_src_operand(Opnd) ->
206
fix_mem_operand(Opnd, hipe_x86_registers:temp0()).
208
fix_dst_operand(Opnd) ->
209
fix_mem_operand(Opnd, hipe_x86_registers:temp1()).
211
fix_mem_operand(Opnd, Reg) -> % -> {[fixupcode], newop}
213
#x86_mem{base=Base,off=Off} ->
214
case is_mem_opnd(Base) of
216
case src_is_pseudo(Off) of
219
true -> % pseudo(reg)
220
Temp = clone(Off, Reg),
221
{[hipe_x86:mk_move(Off, Temp)],
222
Opnd#x86_mem{off=Temp}}
225
Temp = clone(Base, Reg),
226
case src_is_pseudo(Off) of
227
false -> % imm/reg(pseudo)
228
{[hipe_x86:mk_move(Base, Temp)],
229
Opnd#x86_mem{base=Temp}};
230
true -> % pseudo1(pseudo0)
231
{[hipe_x86:mk_move(Base, Temp),
232
hipe_x86:mk_alu('add', Off, Temp)],
233
Opnd#x86_mem{base=Temp, off=hipe_x86:mk_imm(0)}}
240
%%% Check if an operand denotes a memory cell (mem or pseudo).
245
#x86_temp{} -> temp_is_pseudo(Opnd);
249
%%% Check if an operand is a pseudo-Temp.
251
src_is_pseudo(Src) ->
252
case hipe_x86:is_temp(Src) of
253
true -> temp_is_pseudo(Src);
257
temp_is_pseudo(Temp = #x86_temp{type=Type}) ->
258
if Type == 'double'-> false;
260
not(hipe_x86_registers:is_precoloured(hipe_x86:temp_reg(Temp)))
263
%%% Make Reg a clone of Dst (attach Dst's type to Reg).
268
#x86_mem{} -> hipe_x86:mem_type(Dst);
269
#x86_temp{} -> hipe_x86:temp_type(Dst)
271
hipe_x86:mk_temp(Reg, Type).