File 0032-beam_type-Avoid-an-internal-consistency-check-failur.patch of Package erlang

From b837f46ba4c3662b93bb79b56b415dce75e3d71e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 13 Mar 2017 14:46:30 +0100
Subject: [PATCH] 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
---
 lib/compiler/src/beam_type.erl        |  3 +++
 lib/compiler/test/beam_type_SUITE.erl | 22 ++++++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 050c599d6..2b5d558ee 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};
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 492067ef0..7ca544a53 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.
-- 
2.12.0

openSUSE Build Service is sponsored by