File 0076-hipe-Fix-range-analysis-of-calls-with-ignored-res.patch of Package erlang

From 48b5cc3c35e1d94807e9587c222a41c3cd513f64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Magnus=20L=C3=A5ng?= <margnus1@telia.com>
Date: Mon, 27 Mar 2017 15:19:25 +0200
Subject: [PATCH 2/3] hipe: Fix range analysis of calls with ignored res

HiPE's range analysis would not update the arguments of a callee when
the result of the call was ignored.

Fixes ERL-278.
---
 lib/hipe/icode/hipe_icode_range.erl                |  8 ++---
 lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl | 42 ++++++++++++++++++++++
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl
index 9aed40bd6..d1ffb105f 100644
--- a/lib/hipe/icode/hipe_icode_range.erl
+++ b/lib/hipe/icode/hipe_icode_range.erl
@@ -392,14 +392,14 @@ widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) ->
 -spec analyse_call(#icode_call{}, call_fun()) -> #icode_call{}.
 
 analyse_call(Call, LookupFun) ->
+  Args = hipe_icode:args(Call),
+  Fun = hipe_icode:call_fun(Call),
+  Type = hipe_icode:call_type(Call),
+  DstRanges = analyse_call_or_enter_fun(Fun, Args, Type, LookupFun),
   case hipe_icode:call_dstlist(Call) of
     [] ->
       Call;
     Dsts ->
-      Args = hipe_icode:args(Call),
-      Fun = hipe_icode:call_fun(Call),
-      Type = hipe_icode:call_type(Call),
-      DstRanges = analyse_call_or_enter_fun(Fun, Args, Type, LookupFun),
       NewDefs = [update_info(Var, R) || {Var,R} <- lists:zip(Dsts, DstRanges)],
       hipe_icode:subst_defines(lists:zip(Dsts, NewDefs), Call)
   end.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl b/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
index caa0e71d0..430e097b9 100644
--- a/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
+++ b/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
@@ -18,6 +18,7 @@ test() ->
   ok = test_R12B5_seg_fault(),
   ok = test_switch_neg_int(),
   ok = test_icode_range_anal(),
+  ok = test_icode_range_call(),
   ok.
 
 %%-----------------------------------------------------------------------
@@ -461,3 +462,44 @@ g(X, Z) ->
     test -> non_zero_test;
     other -> other
   end.
+
+%%-----------------------------------------------------------------------
+%% From: Rich Neswold
+%% Date: Oct 5, 2016
+%%
+%% The following was a bug in the HiPE compiler's range analysis. The
+%% function range_client/2 below would would not stop when N reached 0,
+%% but keep recursing into the second clause forever.
+%%
+%% The problem turned out to be in hipe_icode_range:analyse_call/2,
+%% which would note update the argument ranges of the callee if the
+%% result of the call was ignored.
+%% -----------------------------------------------------------------------
+-define(TIMEOUT, 42).
+
+test_icode_range_call() ->
+    Self = self(),
+    Client = spawn_link(fun() -> range_client(Self, 4) end),
+    range_server(4, Client).
+
+range_server(0, _Client) ->
+    receive
+        stopping -> ok;
+        {called_with, 0} -> error(failure)
+    after ?TIMEOUT -> error(timeout)
+    end;
+range_server(N, Client) ->
+    receive
+        {called_with, N} ->
+            Client ! proceed
+    after ?TIMEOUT -> error(timeout)
+    end,
+    range_server(N-1, Client). % tailcall (so the bug does not affect it)
+
+range_client(Server, 0) ->
+    Server ! stopping;
+range_client(Server, N) ->
+    Server ! {called_with, N},
+    receive proceed -> ok end,
+    range_client(Server, N - 1), % non-tailrecursive call with ignored result
+    ok.
-- 
2.12.2

openSUSE Build Service is sponsored by