aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/x86/hipe_rtl_to_x86.erl
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-03-12 01:29:24 +0100
committerMagnus Lång <[email protected]>2016-08-30 17:02:39 +0200
commit8acd1a0d56e4ba33d07cdac0b6a829a701145003 (patch)
treeecd7ffcabd305d737b5dc0f69832f9f950008fdd /lib/hipe/x86/hipe_rtl_to_x86.erl
parentd93a42112b35e4dbfb0f34b413fffb543f15ca3e (diff)
downloadotp-8acd1a0d56e4ba33d07cdac0b6a829a701145003.tar.gz
otp-8acd1a0d56e4ba33d07cdac0b6a829a701145003.tar.bz2
otp-8acd1a0d56e4ba33d07cdac0b6a829a701145003.zip
hipe_x86: Be resilient to crappy RTL
The x86 backend crashes if certain RTL optimisations were omitted, preventing it from being usable at lower optimisation levels.
Diffstat (limited to 'lib/hipe/x86/hipe_rtl_to_x86.erl')
-rw-r--r--lib/hipe/x86/hipe_rtl_to_x86.erl19
1 files changed, 15 insertions, 4 deletions
diff --git a/lib/hipe/x86/hipe_rtl_to_x86.erl b/lib/hipe/x86/hipe_rtl_to_x86.erl
index d13f63b1d9..79028b0652 100644
--- a/lib/hipe/x86/hipe_rtl_to_x86.erl
+++ b/lib/hipe/x86/hipe_rtl_to_x86.erl
@@ -144,7 +144,7 @@ conv_insn(I, Map, Data) ->
{I2, Map, Data};
#load{} ->
{Dst, Map0} = conv_dst(hipe_rtl:load_dst(I), Map),
- {FixSrc, Src, Map1} = conv_src(hipe_rtl:load_src(I), Map0),
+ {FixSrc, Src, Map1} = conv_src_noimm(hipe_rtl:load_src(I), Map0),
{FixOff, Off, Map2} = conv_src(hipe_rtl:load_offset(I), Map1),
I2 = case {hipe_rtl:load_size(I), hipe_rtl:load_sign(I)} of
{byte, signed} ->
@@ -171,6 +171,7 @@ conv_insn(I, Map, Data) ->
Src = hipe_x86:mk_imm_from_atom(hipe_rtl:load_atom_atom(I)),
I2 = [hipe_x86:mk_move(Src, Dst)],
{I2, Map0, Data};
+ #move{src=Dst, dst=Dst} -> {[], Map, Data};
#move{} ->
{Dst, Map0} = conv_dst(hipe_rtl:move_dst(I), Map),
{FixSrc, Src, Map1} = conv_src(hipe_rtl:move_src(I), Map0),
@@ -182,11 +183,11 @@ conv_insn(I, Map, Data) ->
I2 = move_retvals(Args, [hipe_x86:mk_ret(-1)]),
{FixArgs++I2, Map0, Data};
#store{} ->
- {Ptr, Map0} = conv_dst(hipe_rtl:store_base(I), Map),
+ {FixPtr, Ptr, Map0} = conv_src_noimm(hipe_rtl:store_base(I), Map),
{FixSrc, Src, Map1} = conv_src(hipe_rtl:store_src(I), Map0),
{FixOff, Off, Map2} = conv_src(hipe_rtl:store_offset(I), Map1),
I2 = mk_store(hipe_rtl:store_size(I), Src, Ptr, Off),
- {FixSrc++FixOff++I2, Map2, Data};
+ {FixPtr++FixSrc++FixOff++I2, Map2, Data};
#switch{} -> % this one also updates Data :-(
%% from hipe_rtl2sparc, but we use a hairy addressing mode
%% instead of doing the arithmetic manually
@@ -206,7 +207,7 @@ conv_insn(I, Map, Data) ->
{I2, Map1, NewData};
#fload{} ->
{Dst, Map0} = conv_dst(hipe_rtl:fload_dst(I), Map),
- {[], Src, Map1} = conv_src(hipe_rtl:fload_src(I), Map0),
+ {[], Src, Map1} = conv_src_noimm(hipe_rtl:fload_src(I), Map0),
{[], Off, Map2} = conv_src(hipe_rtl:fload_offset(I), Map1),
I2 = [hipe_x86:mk_fmove(hipe_x86:mk_mem(Src, Off, 'double'),Dst)],
{I2, Map2, Data};
@@ -572,6 +573,16 @@ conv_fun(Fun, Map) ->
end
end.
+conv_src_noimm(Opnd, Map) ->
+ R={FixSrc0, Src, NewMap} = conv_src(Opnd, Map),
+ case hipe_x86:is_imm(Src) of
+ false -> R;
+ true ->
+ Tmp = new_untagged_temp(),
+ {FixSrc0 ++ [hipe_x86:mk_move(Src, Tmp)],
+ Tmp, NewMap}
+ end.
+
%%% Convert an RTL source operand (imm/var/reg).
conv_src(Opnd, Map) ->