diff options
author | Björn Gustavsson <[email protected]> | 2017-03-13 14:46:30 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-03-13 16:31:22 +0100 |
commit | b837f46ba4c3662b93bb79b56b415dce75e3d71e (patch) | |
tree | 984220a2eacfa2bdc1e6ca1e13f3d257b702ea8b /lib/compiler/test | |
parent | ee1ad99648316f4dc15d872804dfa52990e0240f (diff) | |
download | otp-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/test')
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 492067ef00..7ca544a537 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -22,7 +22,7 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, integers/1,coverage/1,booleans/1,setelement/1,cons/1, - tuple/1]). + tuple/1,record_float/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -37,7 +37,8 @@ groups() -> booleans, setelement, cons, - tuple + tuple, + record_float ]}]. init_per_suite(Config) -> @@ -126,5 +127,22 @@ tuple(_Config) -> do_tuple() -> {0, _} = {necessary}. +-record(x, {a}). + +record_float(_Config) -> + 17.0 = record_float(#x{a={0}}, 1700), + 23.0 = record_float(#x{a={0}}, 2300.0), + {'EXIT',{if_clause,_}} = (catch record_float(#x{a={1}}, 88)), + {'EXIT',{if_clause,_}} = (catch record_float(#x{a={}}, 88)), + {'EXIT',{if_clause,_}} = (catch record_float(#x{}, 88)), + ok. + +record_float(R, N0) -> + N = N0 / 100, + if element(1, R#x.a) =:= 0 -> + N + end. + + id(I) -> I. |