diff options
author | Magnus Lång <[email protected]> | 2016-06-03 18:26:07 +0200 |
---|---|---|
committer | Magnus Lång <[email protected]> | 2016-08-22 15:34:32 +0200 |
commit | a504c30efbc14381385a6ef911ba7296840f8cb7 (patch) | |
tree | 0985a90e08db7c2b90592a2db9a724cd0c7e6752 /lib/hipe | |
parent | b7c2af9863a5410ce0be9c2995ea49746b207877 (diff) | |
download | otp-a504c30efbc14381385a6ef911ba7296840f8cb7.tar.gz otp-a504c30efbc14381385a6ef911ba7296840f8cb7.tar.bz2 otp-a504c30efbc14381385a6ef911ba7296840f8cb7.zip |
hipe: Fix amd64 SSE2 encoding crash
Register allocation could transform something like
fmove u32, d99
to
fmove $rdx, 0x20($rsp)
which is an invalid instruction.
Diffstat (limited to 'lib/hipe')
-rw-r--r-- | lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl b/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl index 5451f1fe7d..b1f7bd7572 100644 --- a/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl +++ b/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl @@ -87,22 +87,29 @@ do_fp_unop(I, TempMap) -> %%% Fix an fmove op. do_fmove(I, TempMap) -> #fmove{src=Src,dst=Dst} = I, - case is_mem_opnd(Dst, TempMap) and is_mem_opnd(Src, TempMap) of + case + (is_mem_opnd(Src, TempMap) andalso is_mem_opnd(Dst, TempMap)) + orelse (is_mem_opnd(Src, TempMap) andalso (not is_float_temp(Dst))) + orelse ((not is_float_temp(Src)) andalso is_mem_opnd(Dst, TempMap)) + of true -> - Tmp = clone(Src), + Tmp = spill_temp(double), {[#fmove{src=Src, dst=Tmp},I#fmove{src=Tmp,dst=Dst}], true}; false -> {[I], false} end. +is_float_temp(#x86_temp{type=Type}) -> Type =:= double; +is_float_temp(#x86_mem{}) -> false. + %%% Check if an operand denotes a memory cell (mem or pseudo). is_mem_opnd(Opnd, TempMap) -> R = case Opnd of #x86_mem{} -> true; - #x86_temp{} -> + #x86_temp{type=double} -> Reg = hipe_x86:temp_reg(Opnd), case hipe_x86:temp_is_allocatable(Opnd) of true -> @@ -176,6 +183,9 @@ clone(Dst) -> #x86_mem{} -> hipe_x86:mem_type(Dst); #x86_temp{} -> hipe_x86:temp_type(Dst) end, + spill_temp(Type). + +spill_temp(Type) -> hipe_x86:mk_new_temp(Type). %%% Make a certain reg into a clone of Dst |