diff options
author | Magnus Lång <[email protected]> | 2016-06-20 18:26:39 +0200 |
---|---|---|
committer | Magnus Lång <[email protected]> | 2016-09-02 15:59:17 +0200 |
commit | 38c10d20f7b0a83f4d94a92d30ca649b86b0a7cb (patch) | |
tree | e9bc6081a91c43bc504a93217e9776c5f1d006d5 /lib/hipe/x86 | |
parent | 86eeae878efbbcfb12245cdab992bb39987f09bf (diff) | |
download | otp-38c10d20f7b0a83f4d94a92d30ca649b86b0a7cb.tar.gz otp-38c10d20f7b0a83f4d94a92d30ca649b86b0a7cb.tar.bz2 otp-38c10d20f7b0a83f4d94a92d30ca649b86b0a7cb.zip |
hipe_x86: Add code rewrite RA callbacks
These will not only be useful for hipe_regalloc_prepass, but also, after
the introduction of a mk_move/2 (or similar) callback, for the purpose
of range splitting.
Since the substitution needed to case over all the instructions, a new
module, hipe_x86_subst, was introduced to the x86 backend.
Due to differences in the 'jtab' field of a #jmp_switch{} between x86
and amd64, it regrettably needed to be duplicated to hipe_amd64_subst.
Diffstat (limited to 'lib/hipe/x86')
-rw-r--r-- | lib/hipe/x86/Makefile | 1 | ||||
-rw-r--r-- | lib/hipe/x86/hipe_x86_subst.erl | 94 |
2 files changed, 95 insertions, 0 deletions
diff --git a/lib/hipe/x86/Makefile b/lib/hipe/x86/Makefile index 9b21270426..84edeaebe7 100644 --- a/lib/hipe/x86/Makefile +++ b/lib/hipe/x86/Makefile @@ -62,6 +62,7 @@ MODULES=hipe_rtl_to_x86 \ hipe_x86_ra_postconditions \ hipe_x86_registers \ hipe_x86_spill_restore \ + hipe_x86_subst \ hipe_x86_x87 HRL_FILES=hipe_x86.hrl diff --git a/lib/hipe/x86/hipe_x86_subst.erl b/lib/hipe/x86/hipe_x86_subst.erl new file mode 100644 index 0000000000..5e642d1d06 --- /dev/null +++ b/lib/hipe/x86/hipe_x86_subst.erl @@ -0,0 +1,94 @@ +%% -*- erlang-indent-level: 2 -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-ifdef(HIPE_AMD64). +-define(HIPE_X86_SUBST, hipe_amd64_subst). +-else. +-define(HIPE_X86_SUBST, hipe_x86_subst). +-endif. + +-module(?HIPE_X86_SUBST). +-export([insn_temps/2]). +-include("../x86/hipe_x86.hrl"). + +%% These should be moved to hipe_x86 and exported +-type temp() :: #x86_temp{}. +-type oper() :: temp() | #x86_imm{} | #x86_mem{}. +-type mfarec() :: #x86_mfa{}. +-type prim() :: #x86_prim{}. +-type funv() :: mfarec() | prim() | temp(). +-type insn() :: tuple(). % for now + +-type subst_fun() :: fun((temp()) -> temp()). + +%% @doc Maps over the temporaries in an instruction +-spec insn_temps(subst_fun(), insn()) -> insn(). +insn_temps(SubstTemp, I) -> + O = fun(O) -> oper_temps(SubstTemp, O) end, + case I of + #alu {src=S, dst=D} -> I#alu {src=O(S), dst=O(D)}; + #cmovcc {src=S, dst=D} -> I#cmovcc {src=O(S), dst=O(D)}; + #cmp {src=S, dst=D} -> I#cmp {src=O(S), dst=O(D)}; + #fmove {src=S, dst=D} -> I#fmove {src=O(S), dst=O(D)}; + #fp_binop{src=S, dst=D} -> I#fp_binop{src=O(S), dst=O(D)}; + #imul {src=S, temp=T} -> I#imul {src=O(S), temp=O(T)}; + #lea {mem=M, temp=T} -> I#lea {mem=O(M), temp=O(T)}; + #move {src=S, dst=D} -> I#move {src=O(S), dst=O(D)}; + #movsx {src=S, dst=D} -> I#movsx {src=O(S), dst=O(D)}; + #movzx {src=S, dst=D} -> I#movzx {src=O(S), dst=O(D)}; + #shift {src=S, dst=D} -> I#shift {src=O(S), dst=O(D)}; + #test {src=S, dst=D} -> I#test {src=O(S), dst=O(D)}; + #fp_unop{arg=A} -> I#fp_unop{arg=O(A)}; + #move64 {dst=D} -> I#move64 {dst=O(D)}; + #push {src=S} -> I#push {src=O(S)}; + #pop {dst=D} -> I#pop {dst=O(D)}; + #jmp_switch{temp=T, jtab=J} -> + I#jmp_switch{temp=O(T), jtab=jtab_temps(SubstTemp, J)}; + #pseudo_call{'fun'=F} -> + I#pseudo_call{'fun'=funv_temps(SubstTemp, F)}; + #pseudo_tailcall{'fun'=F, stkargs=Stk} -> + I#pseudo_tailcall{'fun'=funv_temps(SubstTemp, F), + stkargs=lists:map(O, Stk)}; + #comment{} -> I; + #jmp_label{} -> I; + #pseudo_tailcall_prepare{} -> I; + #pseudo_jcc{} -> I; + #ret{} -> I + end. + +-spec oper_temps(subst_fun(), oper()) -> oper(). +oper_temps(_SubstTemp, I=#x86_imm{}) -> I; +oper_temps(SubstTemp, T=#x86_temp{}) -> SubstTemp(T); +oper_temps(SubstTemp, M=#x86_mem{base=Base,off=Off}) -> + M#x86_mem{base=oper_temps(SubstTemp, Base), + off =oper_temps(SubstTemp, Off)}. + +-spec funv_temps(subst_fun(), funv()) -> funv(). +funv_temps(_SubstTemp, MFA=#x86_mfa{}) -> MFA; +funv_temps(_SubstTemp, P=#x86_prim{}) -> P; +funv_temps(SubstTemp, T=#x86_temp{}) -> SubstTemp(T). + +%% TODO: Undo this ifdeffery at the source (make jtab an #x86_imm{} on x86) +-ifdef(HIPE_AMD64). +jtab_temps(SubstTemp, T=#x86_temp{}) -> SubstTemp(T). +-else. +jtab_temps(_SubstTemp, DataLbl) when is_integer(DataLbl) -> DataLbl. +-endif. |