From e7250092945c7d15063d7b2f8ab50070b2a30786 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Magnus=20L=C3=A5ng?= <margnus1@telia.com>
Date: Sat, 19 Nov 2016 14:26:01 +0100
Subject: hipe: Improve error message on internal crashes

Print the MFA/module being compiled, and pretty-print the backtrace with
lib:format_stacktrace/4.

Additionally, make the error_msg/2 macro in hipe.hrl respect the
HIPE_LOGGING define, since messages produced by this macro just before
runtime shutdown were sometimes lost (since code_server:error_msg/2 is
asynchronous).
---
 lib/hipe/main/hipe.erl     | 89 ++++++++++++++++++++++++++++------------------
 lib/hipe/main/hipe.hrl.src | 10 ++++--
 2 files changed, 62 insertions(+), 37 deletions(-)

(limited to 'lib')

diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index 6c525dd143..38a5a64398 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -635,44 +635,51 @@ run_compiler(Name, DisasmFun, IcodeFun, Opts0) ->
   Opts = expand_basic_options(Opts0 ++ ?COMPILE_DEFAULTS),
   ?when_option(verbose, Opts, ?debug_msg("Compiling: ~p\n",[Name])),
   ?option_start_time("Compile", Opts),
-  Res = run_compiler_1(DisasmFun, IcodeFun, Opts),
+  Res = run_compiler_1(Name, DisasmFun, IcodeFun, Opts),
   ?option_stop_time("Compile", Opts),
   Res.
 
-run_compiler_1(DisasmFun, IcodeFun, Options) ->
+run_compiler_1(Name, DisasmFun, IcodeFun, Options) ->
   Parent = self(),
   {trap_exit,TrapExit} = process_info(Parent, trap_exit),
   %% Spawn a compilation process CompProc. In case this process gets
   %% killed, the trap_exit flag is restored to that of the Parent process.
   process_flag(trap_exit, true),
-  CompProc = spawn_link(fun () ->
-			    %% Compiler process
-			    set_architecture(Options),
-			    pre_init(Options),
-			    %% The full option expansion is not done
-			    %% until the DisasmFun returns.
-			    {Code, CompOpts} = DisasmFun(Options),
-			    Opts0 = expand_options(Options ++ CompOpts,
-                                                   get(hipe_target_arch)),
-                            Opts =
-                             case proplists:get_bool(to_llvm, Opts0) andalso
-                                 not llvm_support_available() of
-                               true ->
-                                 ?error_msg("No LLVM version 3.4 or greater "
-                                            "found in $PATH; aborting "
-                                            "native code compilation.\n", []),
-                                 ?EXIT(cant_find_required_llvm_version);
-                               false ->
-                                 Opts0
-                             end,
-			    check_options(Opts),
-			    ?when_option(verbose, Options,
-					 ?debug_msg("Options: ~p.\n",[Opts])),
-			    init(Opts),
-			    {Icode, WholeModule} = IcodeFun(Code, Opts),
-			    CompRes = compile_finish(Icode, WholeModule, Opts),
-			    compiler_return(CompRes, Parent)
-			end),
+  CompProc =
+    spawn_link(
+      fun () ->
+	  try
+	    %% Compiler process
+	    set_architecture(Options),
+	    pre_init(Options),
+	    %% The full option expansion is not done
+	    %% until the DisasmFun returns.
+	    {Code, CompOpts} = DisasmFun(Options),
+	    Opts0 = expand_options(Options ++ CompOpts,
+				   get(hipe_target_arch)),
+	    Opts =
+	      case proplists:get_bool(to_llvm, Opts0) andalso
+		not llvm_support_available() of
+		true ->
+		  ?error_msg("No LLVM version 3.4 or greater "
+			     "found in $PATH; aborting "
+			     "native code compilation.\n", []),
+		  ?EXIT(cant_find_required_llvm_version);
+		false ->
+		  Opts0
+	      end,
+	    check_options(Opts),
+	    ?when_option(verbose, Options,
+			 ?debug_msg("Options: ~p.\n",[Opts])),
+	    init(Opts),
+	    {Icode, WholeModule} = IcodeFun(Code, Opts),
+	    CompRes = compile_finish(Icode, WholeModule, Opts),
+	    compiler_return(CompRes, Parent)
+	  catch error:Error ->
+	      print_crash_message(Name, Error),
+	      exit(Error)
+	  end
+      end),
   Timeout = case proplists:get_value(timeout, Options) of
 	      N when is_integer(N), N >= 0 -> N;
 	      undefined -> ?DEFAULT_TIMEOUT;
@@ -691,7 +698,7 @@ run_compiler_1(DisasmFun, IcodeFun, Options) ->
       exit(CompProc, kill),
       receive {'EXIT', CompProc, _} -> ok end,
       flush(),
-      ?error_msg("ERROR: Compilation timed out.\n",[]),
+      ?error_msg("ERROR: Compilation of ~w timed out.\n",[Name]),
       exit(timed_out)
   end,
   Result = receive {CompProc, Res} -> Res end,
@@ -844,11 +851,25 @@ finalize_fun_sequential({MFA, Icode}, Opts, Servers) ->
   catch
     error:Error ->
       ?when_option(verbose, Opts, ?debug_untagged_msg("\n", [])),
-      ErrorInfo = {Error, erlang:get_stacktrace()},
-      ?error_msg("ERROR: ~p~n", [ErrorInfo]),
-      ?EXIT(ErrorInfo)
+      print_crash_message(MFA, Error),
+      exit(Error)
   end.
 
+print_crash_message(What, Error) ->
+  StackFun = fun(_,_,_) -> false end,
+  FormatFun = fun (Term, _) -> io_lib:format("~p", [Term]) end,
+  StackTrace = lib:format_stacktrace(1, erlang:get_stacktrace(),
+				     StackFun, FormatFun),
+  WhatS = case What of
+	    {M,F,A} -> io_lib:format("~w:~w/~w", [M,F,A]);
+	    Mod -> io_lib:format("~w", [Mod])
+	  end,
+  ?error_msg("INTERNAL ERROR~n"
+	     "while compiling ~s~n"
+	     "crash reason: ~p~n"
+	     "~s~n",
+	     [WhatS, Error, StackTrace]).
+
 pp_server_start(Opts) ->
   set_architecture(Opts),
   garbage_collect(),
diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src
index 53b59f88f0..08bfd17f30 100644
--- a/lib/hipe/main/hipe.hrl.src
+++ b/lib/hipe/main/hipe.hrl.src
@@ -1,4 +1,4 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- mode: erlang; erlang-indent-level: 2 -*-
 %%
 %% %CopyrightBegin%
 %% 
@@ -70,20 +70,24 @@
 	code_server:info_msg(?MSGTAG ++ Msg, Args)).
 -define(untagged_msg(Msg, Args),
 	code_server:info_msg(Msg, Args)).
+-define(untagged_error_msg(Msg, Args),
+	code_server:error_msg(Msg, Args)).
 -else.
 -define(msg(Msg, Args),
 	io:format(?MSGTAG ++ Msg, Args)).
 -define(untagged_msg(Msg, Args),
 	io:format(Msg, Args)).
+-define(untagged_error_msg(Msg, Args),
+	io:format(Msg, Args)).
 -endif.
 
 %%
 %% Define error and warning messages.
 %%
 -define(error_msg(Msg, Args),
-	code_server:error_msg(?MSGTAG ++
+	?untagged_error_msg(?MSGTAG ++
 			      "Error: [~s:~w]: " ++ Msg,
-			      [?MODULE,?LINE|Args])).
+			    [?MODULE,?LINE|Args])).
 -define(WARNING_MSG(Msg, Args),
 	?msg("Warning: [~s:~w]: " ++ Msg, [?MODULE,?LINE|Args])).
 
-- 
cgit v1.2.3


From bb4624af3e5e1a5979c547e70110a923f1c9d503 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Magnus=20L=C3=A5ng?= <margnus1@telia.com>
Date: Sat, 19 Nov 2016 15:55:45 +0100
Subject: hipe_icode_call_elim: Fix cf elimination crash

hipe_icode_call_elim could in some cases replace an #icode_call{} with
control flow with a move instruction. This would break the control flow
graph invariants and cause a crash.
---
 lib/hipe/icode/hipe_icode_call_elim.erl                    |  3 ++-
 .../test/maps_SUITE_data/maps_redundant_branch_is_key.erl  | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 lib/hipe/test/maps_SUITE_data/maps_redundant_branch_is_key.erl

(limited to 'lib')

diff --git a/lib/hipe/icode/hipe_icode_call_elim.erl b/lib/hipe/icode/hipe_icode_call_elim.erl
index 6a22133962..71c709a7d1 100644
--- a/lib/hipe/icode/hipe_icode_call_elim.erl
+++ b/lib/hipe/icode/hipe_icode_call_elim.erl
@@ -46,7 +46,8 @@ cfg(IcodeSSA) ->
 -spec elim_insn(icode_instr()) -> icode_instr().
 elim_insn(Insn=#icode_call{'fun'={_,_,_}=MFA, args=Args, type=remote,
 			   dstlist=[Dst=#icode_variable{
-				      annotation={type_anno, RetType, _}}]}) ->
+					   annotation={type_anno, RetType, _}}],
+			   continuation=[], fail_label=[]}) ->
   Opaques = 'universe',
   case erl_types:t_is_singleton(RetType, Opaques) of
     true ->
diff --git a/lib/hipe/test/maps_SUITE_data/maps_redundant_branch_is_key.erl b/lib/hipe/test/maps_SUITE_data/maps_redundant_branch_is_key.erl
new file mode 100644
index 0000000000..17c3acd6af
--- /dev/null
+++ b/lib/hipe/test/maps_SUITE_data/maps_redundant_branch_is_key.erl
@@ -0,0 +1,14 @@
+-module(maps_redundant_branch_is_key).
+-export([test/0]).
+
+test() ->
+    ok = thingy(#{a => 1}),
+    ok = thingy(#{a => 2}),
+    ok.
+
+thingy(Map) ->
+    try
+	#{a := _} = Map,
+	ok
+    catch _ -> error
+    end.
-- 
cgit v1.2.3