diff options
author | Björn Gustavsson <[email protected]> | 2018-02-28 06:29:23 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2018-03-02 12:56:35 +0100 |
commit | e5f5bebc9982ea15652dc97711b32348973905b4 (patch) | |
tree | c763bbd02336468b86b329db0c5c56a1dedeb439 /lib/compiler/src | |
parent | 478b43211bbe96018b63cbf6c6d567550a6e8a2c (diff) | |
download | otp-e5f5bebc9982ea15652dc97711b32348973905b4.tar.gz otp-e5f5bebc9982ea15652dc97711b32348973905b4.tar.bz2 otp-e5f5bebc9982ea15652dc97711b32348973905b4.zip |
beam_block: Fix unsafe sinking of get_tuple_element/3
In the following code:
{get_tuple_element,{x,0},0,{x,1}}.
{put_tuple,2,{x,1}}.
{put,{atom,badmap}}.
{put,{x,0}}.
{move,{x,1},{x,0}}.
beam_block would move the get_tuple_element/3 instruction and eliminate the
move/2 instruction:
{put_tuple,2,{x,1}}.
{put,{atom,badmap}}.
{put,{x,0}}.
{get_tuple_element,{x,0},0,{x,0}}.
That is not correct, since the result of the tuple building in {x,1} is
now ignored.
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/beam_block.erl | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 47a2be8ab5..8cd271e1dc 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -363,10 +363,18 @@ opt_tuple_element_1([{set,[D],[S],move}|Is0], I0, {_,S}, Acc) -> case eliminate_use_of_from_reg(Is0, S, D) of no -> no; - {yes,Is} -> + {yes,Is1} -> {set,[S],Ss,Op} = I0, I = {set,[D],Ss,Op}, - {yes,reverse(Acc, [I|Is])} + case opt_move_rev(S, Acc, [I|Is1]) of + not_possible -> + %% Not safe because the move of the + %% get_tuple_element instruction would cause the + %% result of a previous instruction to be ignored. + no; + {_,Is} -> + {yes,Is} + end end; opt_tuple_element_1([{set,Ds,Ss,_}=I|Is], MovedI, {S,D}=Regs, Acc) -> case member(S, Ds) orelse member(D, Ss) of |