aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/x86/hipe_x86_defuse.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/hipe/x86/hipe_x86_defuse.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/hipe/x86/hipe_x86_defuse.erl')
-rw-r--r--lib/hipe/x86/hipe_x86_defuse.erl160
1 files changed, 160 insertions, 0 deletions
diff --git a/lib/hipe/x86/hipe_x86_defuse.erl b/lib/hipe/x86/hipe_x86_defuse.erl
new file mode 100644
index 0000000000..3387f77595
--- /dev/null
+++ b/lib/hipe/x86/hipe_x86_defuse.erl
@@ -0,0 +1,160 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%
+%%% %CopyrightBegin%
+%%%
+%%% Copyright Ericsson AB 2001-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%
+%%%
+%%% compute def/use sets for x86 insns
+%%%
+%%% TODO:
+%%% - represent EFLAGS (condition codes) use/def by a virtual reg?
+%%% - should push use/def %esp?
+
+-ifdef(HIPE_AMD64).
+-define(HIPE_X86_DEFUSE, hipe_amd64_defuse).
+-define(HIPE_X86_REGISTERS, hipe_amd64_registers).
+-define(RV, rax).
+-else.
+-define(HIPE_X86_DEFUSE, hipe_x86_defuse).
+-define(HIPE_X86_REGISTERS, hipe_x86_registers).
+-define(RV, eax).
+-endif.
+
+-module(?HIPE_X86_DEFUSE).
+-export([insn_def/1, insn_use/1]). %% src_use/1]).
+-include("../x86/hipe_x86.hrl").
+
+%%%
+%%% insn_def(Insn) -- Return set of temps defined by an instruction.
+%%%
+
+insn_def(I) ->
+ case I of
+ #alu{dst=Dst} -> dst_def(Dst);
+ #cmovcc{dst=Dst} -> dst_def(Dst);
+ #fmove{dst=Dst} -> dst_def(Dst);
+ #fp_binop{dst=Dst} -> dst_def(Dst);
+ #fp_unop{arg=Arg} -> dst_def(Arg);
+ #imul{temp=Temp} -> [Temp];
+ #lea{temp=Temp} -> [Temp];
+ #move{dst=Dst} -> dst_def(Dst);
+ #move64{dst=Dst} -> dst_def(Dst);
+ #movsx{dst=Dst} -> dst_def(Dst);
+ #movzx{dst=Dst} -> dst_def(Dst);
+ #pseudo_call{} -> call_clobbered();
+ #pseudo_spill{} -> [];
+ #pseudo_tailcall_prepare{} -> tailcall_clobbered();
+ #shift{dst=Dst} -> dst_def(Dst);
+ %% call, cmp, comment, jcc, jmp_fun, jmp_label, jmp_switch, label
+ %% pseudo_jcc, pseudo_tailcall, push, ret
+ _ -> []
+ end.
+
+dst_def(Dst) ->
+ case Dst of
+ #x86_temp{} -> [Dst];
+ #x86_fpreg{} -> [Dst];
+ _ -> []
+ end.
+
+call_clobbered() ->
+ [hipe_x86:mk_temp(R, T)
+ || {R,T} <- ?HIPE_X86_REGISTERS:call_clobbered()].
+
+tailcall_clobbered() ->
+ [hipe_x86:mk_temp(R, T)
+ || {R,T} <- ?HIPE_X86_REGISTERS:tailcall_clobbered()].
+
+%%%
+%%% insn_use(Insn) -- Return set of temps used by an instruction.
+%%%
+
+insn_use(I) ->
+ case I of
+ #alu{src=Src,dst=Dst} -> addtemp(Src, addtemp(Dst, []));
+ #call{'fun'=Fun} -> addtemp(Fun, []);
+ #cmovcc{src=Src, dst=Dst} -> addtemp(Src, dst_use(Dst));
+ #cmp{src=Src, dst=Dst} -> addtemp(Src, addtemp(Dst, []));
+ #fmove{src=Src,dst=Dst} -> addtemp(Src, dst_use(Dst));
+ #fp_unop{arg=Arg} -> addtemp(Arg, []);
+ #fp_binop{src=Src,dst=Dst} -> addtemp(Src, addtemp(Dst, []));
+ #imul{imm_opt=ImmOpt,src=Src,temp=Temp} ->
+ addtemp(Src, case ImmOpt of [] -> addtemp(Temp, []); _ -> [] end);
+ #jmp_fun{'fun'=Fun} -> addtemp(Fun, []);
+ #jmp_switch{temp=Temp, jtab=JTab} -> addtemp(Temp, addtemp(JTab, []));
+ #lea{mem=Mem} -> addtemp(Mem, []);
+ #move{src=Src,dst=Dst} -> addtemp(Src, dst_use(Dst));
+ #move64{} -> [];
+ #movsx{src=Src,dst=Dst} -> addtemp(Src, dst_use(Dst));
+ #movzx{src=Src,dst=Dst} -> addtemp(Src, dst_use(Dst));
+ #pseudo_call{'fun'=Fun,sdesc=#x86_sdesc{arity=Arity}} ->
+ addtemp(Fun, arity_use(Arity));
+ #pseudo_spill{args=Args} -> Args;
+ #pseudo_tailcall{'fun'=Fun,arity=Arity,stkargs=StkArgs} ->
+ addtemp(Fun, addtemps(StkArgs, addtemps(tailcall_clobbered(),
+ arity_use(Arity))));
+ #push{src=Src} -> addtemp(Src, []);
+ #ret{} -> [hipe_x86:mk_temp(?HIPE_X86_REGISTERS:?RV(), 'tagged')];
+ #shift{src=Src,dst=Dst} -> addtemp(Src, addtemp(Dst, []));
+ %% comment, jcc, jmp_label, label, pseudo_jcc, pseudo_tailcall_prepare
+ _ -> []
+ end.
+
+arity_use(Arity) ->
+ [hipe_x86:mk_temp(R, 'tagged')
+ || R <- ?HIPE_X86_REGISTERS:args(Arity)].
+
+dst_use(Dst) ->
+ case Dst of
+ #x86_mem{base=Base,off=Off} -> addbase(Base, addtemp(Off, []));
+ _ -> []
+ end.
+
+%%%
+%%% src_use(Src) -- Return set of temps used by a source operand.
+%%%
+
+%% src_use(Src) ->
+%% addtemp(Src, []).
+
+%%%
+%%% Auxiliary operations on sets of temps
+%%%
+
+addtemps([Arg|Args], Set) ->
+ addtemps(Args, addtemp(Arg, Set));
+addtemps([], Set) ->
+ Set.
+
+addtemp(Arg, Set) ->
+ case Arg of
+ #x86_temp{} -> add(Arg, Set);
+ #x86_mem{base=Base,off=Off} -> addtemp(Off, addbase(Base, Set));
+ #x86_fpreg{} -> add(Arg, Set);
+ _ -> Set
+ end.
+
+addbase(Base, Set) ->
+ case Base of
+ [] -> Set;
+ _ -> addtemp(Base, Set)
+ end.
+
+add(Arg, Set) ->
+ case lists:member(Arg, Set) of
+ false -> [Arg|Set];
+ _ -> Set
+ end.