aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_type.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-03-13 14:46:30 +0100
committerBjörn Gustavsson <[email protected]>2017-03-13 16:31:22 +0100
commitb837f46ba4c3662b93bb79b56b415dce75e3d71e (patch)
tree984220a2eacfa2bdc1e6ca1e13f3d257b702ea8b /lib/compiler/src/beam_type.erl
parentee1ad99648316f4dc15d872804dfa52990e0240f (diff)
downloadotp-b837f46ba4c3662b93bb79b56b415dce75e3d71e.tar.gz
otp-b837f46ba4c3662b93bb79b56b415dce75e3d71e.tar.bz2
otp-b837f46ba4c3662b93bb79b56b415dce75e3d71e.zip
beam_type: Avoid an internal consistency check failure
Code such as the following: -record(x, {a}). f(R, N0) -> N = N0 / 100, if element(1, R#x.a) =:= 0 -> N end. would fail to compile with the following message: m: function f/2+19: Internal consistency check failed - please report this bug. Instruction: {fmove,{fr,0},{x,1}} Error: {uninitialized_reg,{fr,0}}: This bug was introduced in 348b5e6bee2f. Basically, the beam_type pass placed the fmove instruction in the wrong place. Instructions that store to floating point registers and instructions that read from floating point registers are supposed to be in the same basic block. Fix the problem by flushing all floating points instruction before a call the pseudo-BIF is_record/3, thus making sure that the fmove instruction is placed in the correct block. Here is an annotated listing of the relevant part of the .S file (before the fix): {test_heap,{alloc,[{words,0},{floats,1}]},2}. {fconv,{x,1},{fr,0}}. {fmove,{float,100.0},{fr,1}}. fclearerror. {bif,fdiv,{f,0},[{fr,0},{fr,1}],{fr,0}}. {fcheckerror,{f,0}}. %% The instruction {fmove,{fr,0},{x,1}} should have %% been here. %% Block of instructions expanded from a call to %% the pseudo-BIF is_record/3. (Expanded in a later %% compiler pass.) {test,is_tuple,{f,3},[{x,0}]}. {test,test_arity,{f,3},[{x,0},2]}. {get_tuple_element,{x,0},0,{x,2}}. {test,is_eq_exact,{f,3},[{x,2},{atom,x}]}. {move,{atom,true},{x,2}}. {jump,{f,4}}. {label,3}. {move,{atom,false},{x,2}}. {label,4}. %% End of expansion. %% The fmove instruction that beam_validator complains %% about. {fmove,{fr,0},{x,1}}. Reported-by: Richard Carlsson
Diffstat (limited to 'lib/compiler/src/beam_type.erl')
-rw-r--r--lib/compiler/src/beam_type.erl3
1 files changed, 3 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 050c599d6b..2b5d558ee4 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -683,6 +683,9 @@ op_type('bsr') -> integer;
op_type('div') -> integer;
op_type(_) -> unknown.
+flush(Rs, [{set,[_],[_,_,_],{bif,is_record,_}}|_]=Is0, Acc0) ->
+ Acc = flush_all(Rs, Is0, Acc0),
+ {[],Acc};
flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) ->
Acc = flush_all(Rs, Is0, Acc0),
{[],Acc};