diff options
Diffstat (limited to 'lib/hipe')
-rw-r--r-- | lib/hipe/cerl/erl_bif_types.erl | 25 | ||||
-rw-r--r-- | lib/hipe/cerl/erl_types.erl | 221 | ||||
-rw-r--r-- | lib/hipe/doc/src/make.dep | 13 | ||||
-rw-r--r-- | lib/hipe/doc/src/notes.xml | 77 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_beam_to_icode.erl | 72 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_icode_coordinator.erl | 11 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_icode_mulret.erl | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/hipe/icode/hipe_icode_pp.erl | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/hipe/icode/hipe_icode_ssa.erl | 2 | ||||
-rw-r--r-- | lib/hipe/main/hipe.erl | 139 | ||||
-rw-r--r-- | lib/hipe/opt/hipe_schedule.erl | 4 | ||||
-rw-r--r-- | lib/hipe/rtl/Makefile | 26 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl.erl | 5 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_arch.erl | 27 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_lcm.erl | 21 | ||||
-rw-r--r-- | lib/hipe/tools/Makefile | 4 | ||||
-rw-r--r-- | lib/hipe/tools/hipe_ceach.erl | 74 | ||||
-rw-r--r-- | lib/hipe/tools/hipe_profile.erl | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/hipe/util/hipe_dot.erl | 2 | ||||
-rw-r--r-- | lib/hipe/vsn.mk | 2 |
20 files changed, 376 insertions, 361 deletions
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 4163f2dae2..cee399e861 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -678,8 +678,6 @@ type(erlang, check_old_code, 1, Xs) -> type(erlang, check_process_code, 2, Xs) -> strict(arg_types(erlang, check_process_code, 2), Xs, fun (_) -> t_boolean() end); -type(erlang, concat_binary, 1, Xs) -> - strict(arg_types(erlang, concat_binary, 1), Xs, fun (_) -> t_binary() end); type(erlang, crc32, 1, Xs) -> strict(arg_types(erlang, crc32, 1), Xs, fun (_) -> t_crc32() end); type(erlang, crc32, 2, Xs) -> @@ -801,7 +799,8 @@ type(erlang, get_module_info, 2, Xs) -> end end); type(erlang, get_stacktrace, 0, _) -> - t_list(t_tuple([t_atom(), t_atom(), t_sup([t_arity(), t_list()])])); + t_list(t_tuple([t_atom(), t_atom(), t_sup([t_arity(), t_list()]), + t_list()])); type(erlang, group_leader, 0, _) -> t_pid(); type(erlang, group_leader, 2, Xs) -> strict(arg_types(erlang, group_leader, 2), Xs, @@ -1322,6 +1321,9 @@ type(erlang, resume_process, 1, Xs) -> fun (_) -> t_any() end); %% TODO: overapproximation -- fix this type(erlang, round, 1, Xs) -> strict(arg_types(erlang, round, 1), Xs, fun (_) -> t_integer() end); +type(erlang, posixtime_to_universaltime, 1, Xs) -> + strict(arg_types(erlang, posixtime_to_universaltime, 1), Xs, + fun(_) -> t_tuple([t_date(), t_time()]) end); type(erlang, self, 0, _) -> t_pid(); type(erlang, send, 2, Xs) -> type(erlang, '!', 2, Xs); % alias type(erlang, send, 3, Xs) -> @@ -1718,6 +1720,9 @@ type(erlang, universaltime, 0, _) -> type(erlang, universaltime_to_localtime, 1, Xs) -> strict(arg_types(erlang, universaltime_to_localtime, 1), Xs, fun ([T]) -> T end); +type(erlang, universaltime_to_posixtime, 1, Xs) -> + strict(arg_types(erlang, universaltime_to_posixtime,1), Xs, + fun(_) -> t_integer() end); type(erlang, unlink, 1, Xs) -> strict(arg_types(erlang, unlink, 1), Xs, fun (_) -> t_atom('true') end); type(erlang, unregister, 1, Xs) -> @@ -3446,8 +3451,6 @@ arg_types(erlang, check_old_code, 1) -> [t_atom()]; arg_types(erlang, check_process_code, 2) -> [t_pid(), t_atom()]; -arg_types(erlang, concat_binary, 1) -> - [t_list(t_binary())]; arg_types(erlang, crc32, 1) -> [t_iodata()]; arg_types(erlang, crc32, 2) -> @@ -3763,7 +3766,10 @@ arg_types(erlang, purge_module, 1) -> arg_types(erlang, put, 2) -> [t_any(), t_any()]; arg_types(erlang, raise, 3) -> - [t_raise_errorclass(), t_any(), type(erlang, get_stacktrace, 0, [])]; + OldStyleType = t_list(t_tuple([t_atom(), t_atom(), + t_sup([t_arity(), t_list()])])), + NewStyleType = type(erlang, get_stacktrace, 0, []), + [t_raise_errorclass(), t_any(), t_sup(OldStyleType, NewStyleType)]; arg_types(erlang, read_timer, 1) -> [t_reference()]; arg_types(erlang, ref_to_list, 1) -> @@ -3776,6 +3782,8 @@ arg_types(erlang, resume_process, 1) -> [t_pid()]; % intended for debugging only arg_types(erlang, round, 1) -> [t_number()]; +arg_types(erlang, posixtime_to_universaltime, 1) -> + [t_integer()]; arg_types(erlang, self, 0) -> []; arg_types(erlang, send, 2) -> @@ -3881,7 +3889,8 @@ arg_types(erlang, system_flag, 2) -> arg_types(erlang, system_info, 1) -> [t_sup([t_atom(), % documented t_tuple([t_atom(), t_any()]), % documented - t_tuple([t_atom(), t_atom(), t_any()])])]; + t_tuple([t_atom(), t_atom(), t_any()]), + t_tuple([t_atom(allocator_sizes), t_reference(), t_any()])])]; arg_types(erlang, system_monitor, 0) -> []; arg_types(erlang, system_monitor, 1) -> @@ -3941,6 +3950,8 @@ arg_types(erlang, universaltime, 0) -> []; arg_types(erlang, universaltime_to_localtime, 1) -> [t_tuple([t_date(), t_time()])]; +arg_types(erlang, universaltime_to_posixtime, 1) -> + [t_tuple([t_date(), t_time()])]; arg_types(erlang, unlink, 1) -> [t_sup(t_pid(), t_port())]; arg_types(erlang, unregister, 1) -> diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 0ff827ac37..620fed365e 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -2528,34 +2528,77 @@ findfirst(N1, N2, U1, B1, U2, B2) -> %%----------------------------------------------------------------------------- %% Substitution of variables %% +%% Dialyzer versions prior to R15B used a dict data structure to map variables +%% to types. Hans Bolinder suggested the use of lists of Key-Value pairs for +%% this data structure and measurements showed a non-trivial speedup when using +%% them for operations within this module (e.g. in t_unify/2). However, there +%% is code outside erl_types that still passes a dict() in the 2nd argument. +%% So, for the time being, this module provides a t_subst/2 function for these +%% external calls and a clone of it (t_subst_kv/2) which is used from all calls +%% from within this module. This code duplication needs to be eliminated at +%% some point. -spec t_subst(erl_type(), dict()) -> erl_type(). t_subst(T, Dict) -> case t_has_var(T) of - true -> t_subst(T, Dict, fun(X) -> X end); + true -> t_subst_dict(T, Dict); false -> T end. +t_subst_dict(?var(Id), Dict) -> + case dict:find(Id, Dict) of + error -> ?any; + {ok, Type} -> Type + end; +t_subst_dict(?list(Contents, Termination, Size), Dict) -> + case t_subst_dict(Contents, Dict) of + ?none -> ?none; + NewContents -> + %% Be careful here to make the termination collapse if necessary. + case t_subst_dict(Termination, Dict) of + ?nil -> ?list(NewContents, ?nil, Size); + ?any -> ?list(NewContents, ?any, Size); + Other -> + ?list(NewContents, NewTermination, _) = t_cons(NewContents, Other), + ?list(NewContents, NewTermination, Size) + end + end; +t_subst_dict(?function(Domain, Range), Dict) -> + ?function(t_subst_dict(Domain, Dict), t_subst_dict(Range, Dict)); +t_subst_dict(?product(Types), Dict) -> + ?product([t_subst_dict(T, Dict) || T <- Types]); +t_subst_dict(?tuple(?any, ?any, ?any) = T, _Dict) -> + T; +t_subst_dict(?tuple(Elements, _Arity, _Tag), Dict) -> + t_tuple([t_subst_dict(E, Dict) || E <- Elements]); +t_subst_dict(?tuple_set(_) = TS, Dict) -> + t_sup([t_subst_dict(T, Dict) || T <- t_tuple_subtypes(TS)]); +t_subst_dict(T, _Dict) -> + T. + -spec subst_all_vars_to_any(erl_type()) -> erl_type(). subst_all_vars_to_any(T) -> + t_subst_kv(T, []). + +t_subst_kv(T, KVMap) -> case t_has_var(T) of - true -> t_subst(T, dict:new(), fun(_) -> ?any end); + true -> t_subst_aux(T, KVMap); false -> T end. -t_subst(?var(Id) = V, Dict, Fun) -> - case dict:find(Id, Dict) of - error -> Fun(V); - {ok, Type} -> Type +t_subst_aux(?var(Id), VarMap) -> + case lists:keyfind(Id, 1, VarMap) of + false -> ?any; + {Id, Type} -> Type end; -t_subst(?list(Contents, Termination, Size), Dict, Fun) -> - case t_subst(Contents, Dict, Fun) of +t_subst_aux(?list(Contents, Termination, Size), VarMap) -> + case t_subst_aux(Contents, VarMap) of ?none -> ?none; NewContents -> %% Be careful here to make the termination collapse if necessary. - case t_subst(Termination, Dict, Fun) of + case t_subst_aux(Termination, VarMap) of ?nil -> ?list(NewContents, ?nil, Size); ?any -> ?list(NewContents, ?any, Size); Other -> @@ -2563,17 +2606,17 @@ t_subst(?list(Contents, Termination, Size), Dict, Fun) -> ?list(NewContents, NewTermination, Size) end end; -t_subst(?function(Domain, Range), Dict, Fun) -> - ?function(t_subst(Domain, Dict, Fun), t_subst(Range, Dict, Fun)); -t_subst(?product(Types), Dict, Fun) -> - ?product([t_subst(T, Dict, Fun) || T <- Types]); -t_subst(?tuple(?any, ?any, ?any) = T, _Dict, _Fun) -> +t_subst_aux(?function(Domain, Range), VarMap) -> + ?function(t_subst_aux(Domain, VarMap), t_subst_aux(Range, VarMap)); +t_subst_aux(?product(Types), VarMap) -> + ?product([t_subst_aux(T, VarMap) || T <- Types]); +t_subst_aux(?tuple(?any, ?any, ?any) = T, _VarMap) -> T; -t_subst(?tuple(Elements, _Arity, _Tag), Dict, Fun) -> - t_tuple([t_subst(E, Dict, Fun) || E <- Elements]); -t_subst(?tuple_set(_) = TS, Dict, Fun) -> - t_sup([t_subst(T, Dict, Fun) || T <- t_tuple_subtypes(TS)]); -t_subst(T, _Dict, _Fun) -> +t_subst_aux(?tuple(Elements, _Arity, _Tag), VarMap) -> + t_tuple([t_subst_aux(E, VarMap) || E <- Elements]); +t_subst_aux(?tuple_set(_) = TS, VarMap) -> + t_sup([t_subst_aux(T, VarMap) || T <- t_tuple_subtypes(TS)]); +t_subst_aux(T, _VarMap) -> T. %%----------------------------------------------------------------------------- @@ -2590,87 +2633,87 @@ t_unify(T1, T2) -> -spec t_unify(erl_type(), erl_type(), [erl_type()]) -> t_unify_ret(). t_unify(T1, T2, Opaques) -> - {T, Dict} = t_unify(T1, T2, dict:new(), Opaques), - {t_subst(T, Dict), lists:keysort(1, dict:to_list(Dict))}. - -t_unify(?var(Id) = T, ?var(Id), Dict, _Opaques) -> - {T, Dict}; -t_unify(?var(Id1) = T, ?var(Id2), Dict, Opaques) -> - case dict:find(Id1, Dict) of - error -> - case dict:find(Id2, Dict) of - error -> {T, dict:store(Id2, T, Dict)}; - {ok, Type} -> t_unify(T, Type, Dict, Opaques) + {T, VarMap} = t_unify(T1, T2, [], Opaques), + {t_subst_kv(T, VarMap), lists:keysort(1, VarMap)}. + +t_unify(?var(Id) = T, ?var(Id), VarMap, _Opaques) -> + {T, VarMap}; +t_unify(?var(Id1) = T, ?var(Id2), VarMap, Opaques) -> + case lists:keyfind(Id1, 1, VarMap) of + false -> + case lists:keyfind(Id2, 1, VarMap) of + false -> {T, [{Id2, T} | VarMap]}; + {Id2, Type} -> t_unify(T, Type, VarMap, Opaques) end; - {ok, Type1} -> - case dict:find(Id2, Dict) of - error -> {Type1, dict:store(Id2, T, Dict)}; - {ok, Type2} -> t_unify(Type1, Type2, Dict, Opaques) + {Id1, Type1} -> + case lists:keyfind(Id2, 1, VarMap) of + false -> {Type1, [{Id2, T} | VarMap]}; + {Id2, Type2} -> t_unify(Type1, Type2, VarMap, Opaques) end end; -t_unify(?var(Id), Type, Dict, Opaques) -> - case dict:find(Id, Dict) of - error -> {Type, dict:store(Id, Type, Dict)}; - {ok, VarType} -> t_unify(VarType, Type, Dict, Opaques) +t_unify(?var(Id), Type, VarMap, Opaques) -> + case lists:keyfind(Id, 1, VarMap) of + false -> {Type, [{Id, Type} | VarMap]}; + {Id, VarType} -> t_unify(VarType, Type, VarMap, Opaques) end; -t_unify(Type, ?var(Id), Dict, Opaques) -> - case dict:find(Id, Dict) of - error -> {Type, dict:store(Id, Type, Dict)}; - {ok, VarType} -> t_unify(VarType, Type, Dict, Opaques) +t_unify(Type, ?var(Id), VarMap, Opaques) -> + case lists:keyfind(Id, 1, VarMap) of + false -> {Type, [{Id, Type} | VarMap]}; + {Id, VarType} -> t_unify(VarType, Type, VarMap, Opaques) end; -t_unify(?function(Domain1, Range1), ?function(Domain2, Range2), Dict, Opaques) -> - {Domain, Dict1} = t_unify(Domain1, Domain2, Dict, Opaques), - {Range, Dict2} = t_unify(Range1, Range2, Dict1, Opaques), - {?function(Domain, Range), Dict2}; +t_unify(?function(Domain1, Range1), ?function(Domain2, Range2), VarMap, Opaques) -> + {Domain, VarMap1} = t_unify(Domain1, Domain2, VarMap, Opaques), + {Range, VarMap2} = t_unify(Range1, Range2, VarMap1, Opaques), + {?function(Domain, Range), VarMap2}; t_unify(?list(Contents1, Termination1, Size), - ?list(Contents2, Termination2, Size), Dict, Opaques) -> - {Contents, Dict1} = t_unify(Contents1, Contents2, Dict, Opaques), - {Termination, Dict2} = t_unify(Termination1, Termination2, Dict1, Opaques), - {?list(Contents, Termination, Size), Dict2}; -t_unify(?product(Types1), ?product(Types2), Dict, Opaques) -> - {Types, Dict1} = unify_lists(Types1, Types2, Dict, Opaques), - {?product(Types), Dict1}; -t_unify(?tuple(?any, ?any, ?any) = T, ?tuple(?any, ?any, ?any), Dict, _Opaques) -> - {T, Dict}; + ?list(Contents2, Termination2, Size), VarMap, Opaques) -> + {Contents, VarMap1} = t_unify(Contents1, Contents2, VarMap, Opaques), + {Termination, VarMap2} = t_unify(Termination1, Termination2, VarMap1, Opaques), + {?list(Contents, Termination, Size), VarMap2}; +t_unify(?product(Types1), ?product(Types2), VarMap, Opaques) -> + {Types, VarMap1} = unify_lists(Types1, Types2, VarMap, Opaques), + {?product(Types), VarMap1}; +t_unify(?tuple(?any, ?any, ?any) = T, ?tuple(?any, ?any, ?any), VarMap, _Opaques) -> + {T, VarMap}; t_unify(?tuple(Elements1, Arity, _), - ?tuple(Elements2, Arity, _), Dict, Opaques) when Arity =/= ?any -> - {NewElements, Dict1} = unify_lists(Elements1, Elements2, Dict, Opaques), - {t_tuple(NewElements), Dict1}; + ?tuple(Elements2, Arity, _), VarMap, Opaques) when Arity =/= ?any -> + {NewElements, VarMap1} = unify_lists(Elements1, Elements2, VarMap, Opaques), + {t_tuple(NewElements), VarMap1}; t_unify(?tuple_set([{Arity, _}]) = T1, - ?tuple(_, Arity, _) = T2, Dict, Opaques) when Arity =/= ?any -> - unify_tuple_set_and_tuple(T1, T2, Dict, Opaques); + ?tuple(_, Arity, _) = T2, VarMap, Opaques) when Arity =/= ?any -> + unify_tuple_set_and_tuple(T1, T2, VarMap, Opaques); t_unify(?tuple(_, Arity, _) = T1, - ?tuple_set([{Arity, _}]) = T2, Dict, Opaques) when Arity =/= ?any -> - unify_tuple_set_and_tuple(T2, T1, Dict, Opaques); -t_unify(?tuple_set(List1), ?tuple_set(List2), Dict, Opaques) -> - {Tuples, NewDict} = + ?tuple_set([{Arity, _}]) = T2, VarMap, Opaques) when Arity =/= ?any -> + unify_tuple_set_and_tuple(T2, T1, VarMap, Opaques); +t_unify(?tuple_set(List1), ?tuple_set(List2), VarMap, Opaques) -> + {Tuples, NewVarMap} = unify_lists(lists:append([T || {_Arity, T} <- List1]), - lists:append([T || {_Arity, T} <- List2]), Dict, Opaques), - {t_sup(Tuples), NewDict}; -t_unify(?opaque(Elements) = T, ?opaque(Elements), Dict, _Opaques) -> - {T, Dict}; -t_unify(?opaque(_) = T1, ?opaque(_) = T2, _Dict, _Opaques) -> + lists:append([T || {_Arity, T} <- List2]), VarMap, Opaques), + {t_sup(Tuples), NewVarMap}; +t_unify(?opaque(Elements) = T, ?opaque(Elements), VarMap, _Opaques) -> + {T, VarMap}; +t_unify(?opaque(_) = T1, ?opaque(_) = T2, _VarMap, _Opaques) -> throw({mismatch, T1, T2}); -t_unify(Type, ?opaque(_) = OpType, Dict, Opaques) -> - t_unify_with_opaque(Type, OpType, Dict, Opaques); -t_unify(?opaque(_) = OpType, Type, Dict, Opaques) -> - t_unify_with_opaque(Type, OpType, Dict, Opaques); -t_unify(T, T, Dict, _Opaques) -> - {T, Dict}; +t_unify(Type, ?opaque(_) = OpType, VarMap, Opaques) -> + t_unify_with_opaque(Type, OpType, VarMap, Opaques); +t_unify(?opaque(_) = OpType, Type, VarMap, Opaques) -> + t_unify_with_opaque(Type, OpType, VarMap, Opaques); +t_unify(T, T, VarMap, _Opaques) -> + {T, VarMap}; t_unify(T1, T2, _, _) -> throw({mismatch, T1, T2}). -t_unify_with_opaque(Type, OpType, Dict, Opaques) -> +t_unify_with_opaque(Type, OpType, VarMap, Opaques) -> case lists:member(OpType, Opaques) of true -> Struct = t_opaque_structure(OpType), - try t_unify(Type, Struct, Dict, Opaques) of - {_T, Dict1} -> {OpType, Dict1} + try t_unify(Type, Struct, VarMap, Opaques) of + {_T, VarMap1} -> {OpType, VarMap1} catch throw:{mismatch, _T1, _T2} -> case t_inf(OpType, Type, opaque) of ?none -> throw({mismatch, Type, OpType}); - _ -> {OpType, Dict} + _ -> {OpType, VarMap} end end; false -> @@ -2678,20 +2721,20 @@ t_unify_with_opaque(Type, OpType, Dict, Opaques) -> end. unify_tuple_set_and_tuple(?tuple_set([{Arity, List}]), - ?tuple(Elements2, Arity, _), Dict, Opaques) -> + ?tuple(Elements2, Arity, _), VarMap, Opaques) -> %% Can only work if the single tuple has variables at correct places. %% Collapse the tuple set. - {NewElements, Dict1} = unify_lists(sup_tuple_elements(List), Elements2, Dict, Opaques), - {t_tuple(NewElements), Dict1}. + {NewElements, VarMap1} = unify_lists(sup_tuple_elements(List), Elements2, VarMap, Opaques), + {t_tuple(NewElements), VarMap1}. -unify_lists(L1, L2, Dict, Opaques) -> - unify_lists(L1, L2, Dict, [], Opaques). +unify_lists(L1, L2, VarMap, Opaques) -> + unify_lists(L1, L2, VarMap, [], Opaques). -unify_lists([T1|Left1], [T2|Left2], Dict, Acc, Opaques) -> - {NewT, NewDict} = t_unify(T1, T2, Dict, Opaques), - unify_lists(Left1, Left2, NewDict, [NewT|Acc], Opaques); -unify_lists([], [], Dict, Acc, _Opaques) -> - {lists:reverse(Acc), Dict}. +unify_lists([T1|Left1], [T2|Left2], VarMap, Acc, Opaques) -> + {NewT, NewVarMap} = t_unify(T1, T2, VarMap, Opaques), + unify_lists(Left1, Left2, NewVarMap, [NewT|Acc], Opaques); +unify_lists([], [], VarMap, Acc, _Opaques) -> + {lists:reverse(Acc), VarMap}. %%t_assign_variables_to_subtype(T1, T2) -> %% try diff --git a/lib/hipe/doc/src/make.dep b/lib/hipe/doc/src/make.dep deleted file mode 100644 index d5f5844c21..0000000000 --- a/lib/hipe/doc/src/make.dep +++ /dev/null @@ -1,13 +0,0 @@ -# ---------------------------------------------------- -# >>>> Do not edit this file <<<< -# This file was automaticly generated by -# /home/otp/bin/docdepend -# ---------------------------------------------------- - - -# ---------------------------------------------------- -# TeX files that the DVI file depend on -# ---------------------------------------------------- - -book.dvi: book.tex - diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index 6b601e3039..3f28cf9959 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -30,6 +30,83 @@ </header> <p>This document describes the changes made to HiPE.</p> +<section><title>Hipe 3.9</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + <list> <item><p>No warnings for underspecs with remote + types</p></item> <item><p> Fix crash in Typer</p></item> + <item><p>Fix Dialyzer's warning for its own + code</p></item> <item><p>Fix Dialyzer's warnings in + HiPE</p></item> <item><p>Add file/line info in a + particular Dialyzer crash</p></item> <item><p>Update + inets test results</p></item> </list></p> + <p> + Own Id: OTP-9758</p> + </item> + <item> + <p> + <list> <item><p>Correct callback spec in application + module</p></item> <item><p>Refine warning about callback + specs with extra ranges</p></item> <item><p>Cleanup + autoimport compiler directives</p></item> <item><p>Fix + Dialyzer's warnings in typer</p></item> <item><p>Fix + Dialyzer's warning for its own code</p></item> + <item><p>Fix bug in Dialyzer's behaviours + analysis</p></item> <item><p>Fix crash in + Dialyzer</p></item> <item><p>Variable substitution was + not generalizing any unknown variables.</p></item> + </list></p> + <p> + Own Id: OTP-9776</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Possible to run HiPE without floating point exceptions + (FPE). Useful on platforms that lack reliable FPE. Slower + float operations compared to HiPE with FPE.</p> + <p> + Own Id: OTP-9724</p> + </item> + <item> + <p> + HiPE compiler: The possibility to compile and load + selected functions from a module has been removed.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-9751</p> + </item> + <item> + <p> + <c>filename:find_src/1,2</c> will now work on stripped + BEAM files (reported by Per Hedeland). The HiPE compiler + will also work on stripped BEAM files. The BEAM compiler + will no longer include compilation options given in the + source code itself in <c>M:module_info(compile)</c> + (because those options will be applied anyway if the + module is re-compiled).</p> + <p> + Own Id: OTP-9752</p> + </item> + <item> + <p> Optimize <c>erl_types:t_unify()</c>. </p> + <p> + Own Id: OTP-9768</p> + </item> + </list> + </section> + +</section> + <section><title>Hipe 3.8.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index cfed410240..992f387bd5 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -31,7 +31,7 @@ -module(hipe_beam_to_icode). --export([module/2, mfa/3]). +-export([module/2]). %%----------------------------------------------------------------------- @@ -111,55 +111,6 @@ trans_beam_function_chunk(FunBeamCode, ClosureInfo) -> {MFA,Icode}. %%----------------------------------------------------------------------- -%% @doc -%% Translates the BEAM code of a single function into Icode. -%% Returns a tuple whose first argument is list of {{M,F,A}, ICode} -%% pairs, where the first entry is that of the given MFA, and the -%% following (in undefined order) are those of the funs that are -%% defined in the function, and recursively, in the funs. The -%% second argument of the tuple is the HiPE compiler options -%% contained in the file. -%% @end -%%----------------------------------------------------------------------- - --spec mfa(list(), mfa(), comp_options()) -> hipe_beam_to_icode_ret(). - -mfa(BeamFuns, {M,F,A} = MFA, Options) - when is_atom(M), is_atom(F), is_integer(A) -> - BeamCode0 = [beam_disasm:function__code(Fn) || Fn <- BeamFuns], - {ModCode, ClosureInfo} = preprocess_code(BeamCode0), - mfa_loop([MFA], [], sets:new(), ModCode, ClosureInfo, Options). - -mfa_loop([{M,F,A} = MFA | MFAs], Acc, Seen, ModCode, ClosureInfo, - Options) when is_atom(M), is_atom(F), is_integer(A) -> - case sets:is_element(MFA, Seen) of - true -> - mfa_loop(MFAs, Acc, Seen, ModCode, ClosureInfo, Options); - false -> - {Icode, FunMFAs} = mfa_get(M, F, A, ModCode, ClosureInfo, Options), - mfa_loop(FunMFAs ++ MFAs, [{MFA, Icode} | Acc], - sets:add_element(MFA, Seen), - ModCode, ClosureInfo, Options) - end; -mfa_loop([], Acc, _, _, _, _) -> - lists:reverse(Acc). - -mfa_get(M, F, A, ModCode, ClosureInfo, Options) -> - BeamCode = get_fun(ModCode, M,F,A), - pp_beam([BeamCode], Options), % cheat by using a list - Icode = trans_mfa_code(M,F,A, BeamCode, ClosureInfo), - FunMFAs = get_fun_mfas(BeamCode), - {Icode, FunMFAs}. - -get_fun_mfas([{patched_make_fun,{M,F,A} = MFA,_,_,_}|BeamCode]) - when is_atom(M), is_atom(F), is_integer(A) -> - [MFA|get_fun_mfas(BeamCode)]; -get_fun_mfas([_|BeamCode]) -> - get_fun_mfas(BeamCode); -get_fun_mfas([]) -> - []. - -%%----------------------------------------------------------------------- %% The main translation function. %%----------------------------------------------------------------------- @@ -281,10 +232,14 @@ needs_redtest(Leafness) -> %%----------------------------------------------------------------------- %%--- label & func_info combo --- +trans_fun([{label,_}=F,{func_info,_,_,_}=FI|Instructions], Env) -> + %% Handle old code without a line instruction. + trans_fun([F,{line,[]},FI|Instructions], Env); trans_fun([{label,B},{label,_}, {func_info,M,F,A},{label,L}|Instructions], Env) -> trans_fun([{label,B},{func_info,M,F,A},{label,L}|Instructions], Env); trans_fun([{label,B}, + {line,_}, {func_info,{atom,_M},{atom,_F},_A}, {label,L}|Instructions], Env) -> %% Emit code to handle function_clause errors. The BEAM test instructions @@ -1142,6 +1097,11 @@ trans_fun([{trim,N,NY}|Instructions], Env) -> Moves = trans_trim(N, NY), Moves ++ trans_fun(Instructions, Env); %%-------------------------------------------------------------------- +%% New line/1 instruction in R15. +%%-------------------------------------------------------------------- +trans_fun([{line,_}|Instructions], Env) -> + trans_fun(Instructions,Env); +%%-------------------------------------------------------------------- %%--- ERROR HANDLING --- %%-------------------------------------------------------------------- trans_fun([X|_], _) -> @@ -1869,20 +1829,12 @@ patch_make_funs([], FunIndex, Acc) -> find_mfa([{label,_}|Code]) -> find_mfa(Code); +find_mfa([{line,_}|Code]) -> + find_mfa(Code); find_mfa([{func_info,{atom,M},{atom,F},A}|_]) when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 -> {M, F, A}. -%%----------------------------------------------------------------------- - -%% Localize a particular function in a module -get_fun([[L, {func_info,{atom,M},{atom,F},A} | Is] | _], M,F,A) -> - [L, {func_info,{atom,M},{atom,F},A} | Is]; -get_fun([[_L1,_L2, {func_info,{atom,M},{atom,F},A} = MFA| _Is] | _], M,F,A) -> - ?WARNING_MSG("Consecutive labels found; please re-create the .beam file~n", []), - [_L1,_L2, MFA | _Is]; -get_fun([_|Rest], M,F,A) -> - get_fun(Rest, M,F,A). %%----------------------------------------------------------------------- %% Takes a list of arguments and returns the constants of them into diff --git a/lib/hipe/icode/hipe_icode_coordinator.erl b/lib/hipe/icode/hipe_icode_coordinator.erl index a71e143192..d8c82cf01c 100644 --- a/lib/hipe/icode/hipe_icode_coordinator.erl +++ b/lib/hipe/icode/hipe_icode_coordinator.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -49,6 +49,12 @@ coordinate(CG, Escaping, NonEscaping, Mod) -> fun (PM) -> last_action(PM, ServerPid, Mod, All) end, coordinate({Clean,All}, CG, gb_trees:empty(), Restart, LastAction, ServerPid). +-type mfalists() :: {[mfa()], [mfa()]}. + +-spec coordinate(mfalists(), hipe_digraph:hdg(), gb_tree(), + fun((mfalists(), gb_tree()) -> mfalists()), + fun((gb_tree()) -> 'ok'), pid()) -> no_return(). + coordinate(MFALists, CG, PM, Restart, LastAction, ServerPid) -> case MFALists of {[], []} -> @@ -106,8 +112,7 @@ last_action(PM, ServerPid, Mod, All) -> receive {done_rewrite, MFA} -> ok end - end, All), - ok. + end, All). restart_funs({Queue, Busy} = QB, PM, All, ServerPid) -> case ?MAX_CONCURRENT - length(Busy) of diff --git a/lib/hipe/icode/hipe_icode_mulret.erl b/lib/hipe/icode/hipe_icode_mulret.erl index a6529c8519..a3cae621ab 100644 --- a/lib/hipe/icode/hipe_icode_mulret.erl +++ b/lib/hipe/icode/hipe_icode_mulret.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -595,9 +595,9 @@ optimizeDefine([I|Code], Dsts, DstLst, Res) -> [Ds] = Dsts, case isCallPrimop(I, mktuple) andalso DstLst =:= [] of true -> - case (hipe_icode:call_dstlist(I) =:= Dsts) of + case hipe_icode:call_dstlist(I) =:= Dsts of true -> - case (hipe_icode:call_args(I) > 1) of + case length(hipe_icode:call_args(I)) > 1 of true -> optimizeDefine(Code, Dsts, hipe_icode:call_args(I), Res); false -> diff --git a/lib/hipe/icode/hipe_icode_pp.erl b/lib/hipe/icode/hipe_icode_pp.erl index 575bbfe43d..de29b6f779 100755..100644 --- a/lib/hipe/icode/hipe_icode_pp.erl +++ b/lib/hipe/icode/hipe_icode_pp.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% Copyright Ericsson AB 2003-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/icode/hipe_icode_ssa.erl b/lib/hipe/icode/hipe_icode_ssa.erl index 719d5d8f45..4607a96dda 100755..100644 --- a/lib/hipe/icode/hipe_icode_ssa.erl +++ b/lib/hipe/icode/hipe_icode_ssa.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% Copyright Ericsson AB 2002-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index 570e4d9d17..309d847374 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -47,9 +47,8 @@ %% %% <h3>Using the direct interface - for advanced users only</h3> %% -%% To compile a module or a specific function to native code and -%% automatically load the code into memory, call <a -%% href="#c-1"><code>hipe:c(Module)</code></a> or <a +%% To compile a module to native code and automatically load the code +%% into memory, call <a href="#c-1"><code>hipe:c(Module)</code></a> or <a %% href="#c-2"><code>hipe:c(Module, Options)</code></a>. Note that all %% options are specific to the HiPE compiler. See the <a %% href="#index">function index</a> for other compiler functions. @@ -221,11 +220,10 @@ %%------------------------------------------------------------------- -type mod() :: atom(). --type c_unit() :: mod() | mfa(). -type f_unit() :: mod() | binary(). -type ret_rtl() :: [_]. --type c_ret() :: {'ok', c_unit()} | {'error', term()} | - {'ok', c_unit(), ret_rtl()}. %% The last for debugging only +-type c_ret() :: {'ok', mod()} | {'error', term()} | + {'ok', mod(), ret_rtl()}. %% The last for debugging only -type compile_file() :: atom() | string() | binary(). -type compile_ret() :: {hipe_architecture(), binary()} | list(). @@ -278,47 +276,44 @@ load(Mod, BeamFileName) when is_list(BeamFileName) -> end. %% @spec c(Name) -> {ok, Name} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% Reason = term() %% %% @equiv c(Name, []) --spec c(c_unit()) -> c_ret(). +-spec c(mod()) -> c_ret(). c(Name) -> c(Name, []). %% @spec c(Name, options()) -> {ok, Name} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% options() = [option()] %% option() = term() %% Reason = term() %% -%% @type mfa() = {M::mod(),F::fun(),A::arity()}. -%% A fully qualified function name. -%% %% @type fun() = atom(). A function identifier. %% %% @type arity() = integer(). A function arity; always nonnegative. %% %% @doc User-friendly native code compiler interface. Reads BEAM code -%% from the corresponding "Module<code>.beam</code>" file in the system -%% path, and compiles either a single function or the whole module to -%% native code. By default, the compiled code is loaded directly. See -%% above for documentation of options. +%% from the corresponding "Module<code>.beam</code>" file in the +%% system path, and compiles the whole module to native code. By +%% default, the compiled code is loaded directly. See above for +%% documentation of options. %% %% @see c/1 %% @see c/3 %% @see f/2 %% @see compile/2 --spec c(c_unit(), comp_options()) -> c_ret(). +-spec c(mod(), comp_options()) -> c_ret(). c(Name, Options) -> c(Name, beam_file(Name), Options). %% @spec c(Name, File, options()) -> {ok, Name} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% File = filename() | binary() %% Reason = term() %% @@ -329,7 +324,6 @@ c(Name, Options) -> %% @see f/2 c(Name, File, Opts) -> - %% No server if only one function is compiled Opts1 = user_compile_opts(Opts), case compile(Name, File, Opts1) of {ok, Res} -> @@ -359,8 +353,7 @@ f(File) -> %% Reason = term() %% %% @doc Like <code>c/3</code>, but takes the module name from the -%% specified <code>File</code>. This always compiles the whole module; -%% there is no possibility to compile just a single function. +%% specified <code>File</code>. %% %% @see c/3 @@ -381,26 +374,26 @@ user_compile_opts(Opts) -> %% @spec compile(Name) -> {ok, {Target,Binary}} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% Binary = binary() %% Reason = term() %% %% @equiv compile(Name, []) --spec compile(c_unit()) -> {'ok', compile_ret()} | {'error', term()}. +-spec compile(mod()) -> {'ok', compile_ret()} | {'error', term()}. compile(Name) -> compile(Name, []). %% @spec compile(Name, options()) -> {ok, {Target,Binary}} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% Binary = binary() %% Reason = term() %% -%% @doc Direct compiler interface, for advanced use. This just compiles -%% the named function or module, reading BEAM code from the -%% corresponding "Module<code>.beam</code>" file in the system path. -%% Returns <code>{ok, Binary}</code> if successful, or <code>{error, +%% @doc Direct compiler interface, for advanced use. This just +%% compiles the module, reading BEAM code from the corresponding +%% "Module<code>.beam</code>" file in the system path. Returns +%% <code>{ok, Binary}</code> if successful, or <code>{error, %% Reason}</code> otherwise. By default, it does <em>not</em> load the %% binary to memory (the <code>load</code> option can be used to %% activate automatic loading). <code>File</code> can be either a file @@ -412,15 +405,13 @@ compile(Name) -> %% @see file/2 %% @see load/2 --spec compile(c_unit(), comp_options()) -> {'ok', compile_ret()} | {'error', _}. +-spec compile(mod(), comp_options()) -> {'ok', compile_ret()} | {'error', _}. compile(Name, Options) -> compile(Name, beam_file(Name), Options). --spec beam_file(mod() | mfa()) -> string(). +-spec beam_file(mod()) -> string(). -beam_file({M,F,A}) when is_atom(M), is_atom(F), is_integer(A), A >= 0 -> - beam_file(M); beam_file(Module) when is_atom(Module) -> case code:which(Module) of non_existing -> @@ -432,7 +423,7 @@ beam_file(Module) when is_atom(Module) -> %% @spec compile(Name, File, options()) -> %% {ok, {Target, Binary}} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% File = filename() | binary() %% Binary = binary() %% Reason = term() @@ -442,18 +433,11 @@ beam_file(Module) when is_atom(Module) -> %% %% @see compile/2 --spec compile(c_unit(), compile_file(), comp_options()) -> +-spec compile(mod(), compile_file(), comp_options()) -> {'ok', compile_ret()} | {'error', term()}. -compile(Name, File, Opts0) -> - Opts1 = expand_kt2(Opts0), - Opts = - case Name of - {_Mod, _Fun, _Arity} -> - [no_concurrent_comp|Opts1]; - _ -> - Opts1 - end, +compile(Name, File, Opts0) when is_atom(Name) -> + Opts = expand_kt2(Opts0), case proplists:get_value(core, Opts) of true when is_binary(File) -> ?error_msg("Cannot get Core Erlang code from BEAM binary.",[]), @@ -486,23 +470,11 @@ compile(Name, File, Opts0) -> ?EXIT({cant_compile_source_code, Error}) end; Other when Other =:= false; Other =:= undefined -> - NewOpts = - case proplists:get_value(use_callgraph, Opts) of - No when No =:= false; No =:= undefined -> Opts; - _ -> - case Name of - {_M,_F,_A} -> - %% There is no point in using the callgraph or concurrent_comp - %% when analyzing just one function. - [no_use_callgraph, no_concurrent_comp|Opts]; - _ -> Opts - end - end, DisasmFun = fun (_) -> disasm(File) end, IcodeFun = fun (Code, Opts_) -> get_beam_icode(Name, Code, File, Opts_) end, - run_compiler(Name, DisasmFun, IcodeFun, NewOpts) + run_compiler(Name, DisasmFun, IcodeFun, Opts) end. -spec compile_core(mod(), cerl:c_module(), compile_file(), comp_options()) -> @@ -602,9 +574,13 @@ file(File, Options) when is_atom(File) -> disasm(File) -> case beam_disasm:file(File) of #beam_file{labeled_exports = LabeledExports, - compile_info = CompInfo, + compile_info = CompInfo0, code = BeamCode} -> - {options, CompOpts} = lists:keyfind(options, 1, CompInfo), + CompInfo = case CompInfo0 of + none -> []; + _ -> CompInfo0 + end, + CompOpts = proplists:get_value(options, CompInfo, []), HCompOpts = case lists:keyfind(hipe, 1, CompOpts) of {hipe, L} when is_list(L) -> L; {hipe, X} -> [X]; @@ -625,11 +601,6 @@ fix_beam_exports([{F,A,_}|BeamExports], Exports) -> fix_beam_exports([], Exports) -> Exports. -get_beam_icode({M,_F,_A} = MFA, {BeamCode, Exports}, _File, Options) -> - ?option_time({ok, Icode} = - (catch {ok, hipe_beam_to_icode:mfa(BeamCode, MFA, Options)}), - "BEAM-to-Icode", Options), - {{M, Exports, Icode}, false}; get_beam_icode(Mod, {BeamCode, Exports}, File, Options) -> ?option_time({ok, Icode} = (catch {ok, hipe_beam_to_icode:module(BeamCode, Options)}), @@ -899,7 +870,8 @@ maybe_load(Mod, Bin, WholeModule, Opts) -> do_load(Mod, Bin, WholeModule) end. -do_load(Mod, Bin, WholeModule) -> +do_load(Mod, Bin, BeamBinOrPath) when is_binary(BeamBinOrPath); + is_list(BeamBinOrPath) -> HostArch = get(hipe_host_arch), TargetArch = get(hipe_target_arch), %% Make sure we can do the load. @@ -907,29 +879,22 @@ do_load(Mod, Bin, WholeModule) -> ?EXIT({host_and_target_arch_differ, HostArch, TargetArch}); true -> ok end, - case WholeModule of + case code:is_sticky(Mod) of + true -> + %% We unpack and repack the Beam binary as a workaround to + %% ensure that it is not compressed. + {ok, _, Chunks} = beam_lib:all_chunks(BeamBinOrPath), + {ok, Beam} = beam_lib:build_module(Chunks), + %% Don't purge or register sticky mods; just load native. + code:load_native_sticky(Mod, Bin, Beam); false -> - %% In this case, the emulated code for the module must be loaded. - {module, Mod} = code:ensure_loaded(Mod), - code:load_native_partial(Mod, Bin); - BeamBinOrPath when is_binary(BeamBinOrPath) orelse is_list(BeamBinOrPath) -> - case code:is_sticky(Mod) of - true -> - %% We unpack and repack the Beam binary as a workaround to - %% ensure that it is not compressed. - {ok, _, Chunks} = beam_lib:all_chunks(WholeModule), - {ok, Beam} = beam_lib:build_module(Chunks), - %% Don't purge or register sticky mods; just load native. - code:load_native_sticky(Mod, Bin, Beam); - false -> - %% Normal loading of a whole module - Architecture = erlang:system_info(hipe_architecture), - ChunkName = hipe_unified_loader:chunk_name(Architecture), - {ok, _, Chunks0} = beam_lib:all_chunks(WholeModule), - Chunks = [{ChunkName, Bin}|lists:keydelete(ChunkName, 1, Chunks0)], - {ok, BeamPlusNative} = beam_lib:build_module(Chunks), - code:load_binary(Mod, code:which(Mod), BeamPlusNative) - end + %% Normal loading of a whole module + Architecture = erlang:system_info(hipe_architecture), + ChunkName = hipe_unified_loader:chunk_name(Architecture), + {ok, _, Chunks0} = beam_lib:all_chunks(BeamBinOrPath), + Chunks = [{ChunkName, Bin}|lists:keydelete(ChunkName, 1, Chunks0)], + {ok, BeamPlusNative} = beam_lib:build_module(Chunks), + code:load_binary(Mod, code:which(Mod), BeamPlusNative) end. assemble(CompiledCode, Closures, Exports, Options) -> diff --git a/lib/hipe/opt/hipe_schedule.erl b/lib/hipe/opt/hipe_schedule.erl index 4925b2927b..4f153e17ad 100644 --- a/lib/hipe/opt/hipe_schedule.erl +++ b/lib/hipe/opt/hipe_schedule.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -797,7 +797,7 @@ dep_arc(N, Lat, M, {Dag,Preds}) -> %% Returns : A dependence graph sorted by To. %% Description : A new arc that is added is sorted in the right place, and if %% there is already an arc between nodes A and B, the one with -%% the greatest latency is choosen. +%% the greatest latency is chosen. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% add_arc(Lat,To, []) -> {[{Lat, To}], added}; add_arc(Lat1, To, [{Lat2, To} | Arcs]) -> diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile index 55d20af8af..690045b978 100644 --- a/lib/hipe/rtl/Makefile +++ b/lib/hipe/rtl/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2001-2010. All Rights Reserved. +# Copyright Ericsson AB 2001-2011. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -108,10 +108,30 @@ release_spec: opt release_docs_spec: -HIPE_MKLITERALS=$(ERL_TOP)/bin/$(TARGET)/hipe_mkliterals +ifeq ($(TYPE),debug) +TYPE_STR=.debug +else +TYPE_STR= +endif + +ifeq ($(FLAVOR),smp) +FLAVOR_STR=.smp +else +FLAVOR_STR= +endif + +ifeq ($(XCOMP),yes) +MKLIT_FLAGS= -x +else +MKLIT_FLAGS= +endif + + +HIPE_MKLITERALS=$(ERL_TOP)/bin/$(TARGET)/hipe_mkliterals$(TYPE_STR)$(FLAVOR_STR) + hipe_literals.hrl: $(HIPE_MKLITERALS) - $(HIPE_MKLITERALS) -e > hipe_literals.hrl + $(HIPE_MKLITERALS) $(MKLIT_FLAGS) -e > hipe_literals.hrl # Need to generate hipe.hrl from one and only one target in one and only # one makefile; otherwise, clearmake will force rebuilds of hipe over and diff --git a/lib/hipe/rtl/hipe_rtl.erl b/lib/hipe/rtl/hipe_rtl.erl index 29e9c8c8fe..4bf4eb6bd7 100644 --- a/lib/hipe/rtl/hipe_rtl.erl +++ b/lib/hipe/rtl/hipe_rtl.erl @@ -781,8 +781,11 @@ fstore_src_update(F, NewSrc) -> F#fstore{src=NewSrc}. %% fp %% + mk_fp(Dst, Src1, Op, Src2) -> - #fp{dst=Dst, src1=Src1, op=Op, src2=Src2}. + [#fp{dst=Dst, src1=Src1, op=Op, src2=Src2} + | hipe_rtl_arch:mk_fp_check_result(Dst)]. + fp_dst(#fp{dst=Dst}) -> Dst. fp_dst_update(Fp, NewDst) -> Fp#fp{dst=NewDst}. fp_src1(#fp{src1=Src1}) -> Src1. diff --git a/lib/hipe/rtl/hipe_rtl_arch.erl b/lib/hipe/rtl/hipe_rtl_arch.erl index 22cda57a3a..99eb80f3d1 100644 --- a/lib/hipe/rtl/hipe_rtl_arch.erl +++ b/lib/hipe/rtl/hipe_rtl_arch.erl @@ -65,7 +65,8 @@ %% alignment/0, nr_of_return_regs/0, log2_word_size/0, - word_size/0 + word_size/0, + mk_fp_check_result/1 ]). -include("hipe_literals.hrl"). @@ -558,6 +559,12 @@ eval_cond_bits(Cond, N, Z, V, C) -> %%---------------------------------------------------------------------- fwait() -> + case ?ERTS_NO_FPE_SIGNALS of + 1 -> []; + 0 -> fwait_real() + end. + +fwait_real() -> case get(hipe_target_arch) of x86 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)]; amd64 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)]; @@ -573,6 +580,12 @@ fwait() -> %% Returns RTL code to restore the FPU after a floating-point exception. %% @end handle_fp_exception() -> + case ?ERTS_NO_FPE_SIGNALS of + 1 -> []; + 0 -> handle_real_fp_exception() + end. + +handle_real_fp_exception() -> case get(hipe_target_arch) of x86 -> ContLbl = hipe_rtl:mk_new_label(), @@ -655,3 +668,15 @@ nr_of_return_regs() -> 1 %% hipe_amd64_registers:nr_rets(); end. + + +mk_fp_check_result(Result) -> + case ?ERTS_NO_FPE_SIGNALS of + 0 -> + []; + 1 -> + [hipe_rtl:mk_fstore(proc_pointer(), + hipe_rtl:mk_imm(?P_FLOAT_RESULT), + Result), + hipe_rtl:mk_call([], emulate_fpe, [], [], [], not_remote)] + end. diff --git a/lib/hipe/rtl/hipe_rtl_lcm.erl b/lib/hipe/rtl/hipe_rtl_lcm.erl index 9224623c8b..262aedb409 100644 --- a/lib/hipe/rtl/hipe_rtl_lcm.erl +++ b/lib/hipe/rtl/hipe_rtl_lcm.erl @@ -486,7 +486,7 @@ lcm_precalc(CFG, Options) -> ?option_time(NodeInfo2 = calc_down_exp(CFG, ExprMap, NodeInfo1, Labels), "RTL LCM calc_down_exp", Options), ?option_time(NodeInfo3 = calc_killed_expr(CFG, NodeInfo2, UseMap, AllExpr, - Labels), + IdMap, Labels), "RTL LCM calc_killed_exp", Options), ?option_time(NodeInfo4 = calc_avail(CFG, NodeInfo3), "RTL LCM calc_avail", Options), @@ -815,19 +815,19 @@ exp_kill_expr(Instr, [CheckedExpr|Exprs]) -> %%============================================================================= %% Calculates the killed expression sets for all given labels. -calc_killed_expr(_, NodeInfo, _, _, []) -> +calc_killed_expr(_, NodeInfo, _, _, _, []) -> NodeInfo; -calc_killed_expr(CFG, NodeInfo, UseMap, AllExpr, [Label|Labels]) -> +calc_killed_expr(CFG, NodeInfo, UseMap, AllExpr, IdMap, [Label|Labels]) -> Code = hipe_bb:code(hipe_rtl_cfg:bb(CFG, Label)), - KilledExprs = calc_killed_expr_bb(Code, UseMap, AllExpr, ?SETS:new()), + KilledExprs = calc_killed_expr_bb(Code, UseMap, AllExpr, IdMap, ?SETS:new()), NewNodeInfo = set_killed_expr(NodeInfo, Label, KilledExprs), - calc_killed_expr(CFG, NewNodeInfo, UseMap, AllExpr, Labels). + calc_killed_expr(CFG, NewNodeInfo, UseMap, AllExpr, IdMap, Labels). %%============================================================================= %% Calculates the killed expressions set for one basic block. -calc_killed_expr_bb([], _UseMap, _AllExpr, KilledExprs) -> +calc_killed_expr_bb([], _UseMap, _AllExpr, _IdMap, KilledExprs) -> KilledExprs; -calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) -> +calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, IdMap, KilledExprs) -> %% Calls, gctests and stores potentially clobber everything case Instr of #call{} -> AllExpr; @@ -837,7 +837,8 @@ calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) -> %% Kill all float expressions %% FIXME: Make separate function is_fp_expr ?SETS:from_list - (lists:foldl(fun(Expr, Fexprs) -> + (lists:foldl(fun(ExprId, Fexprs) -> + Expr = expr_id_map_get_expr(IdMap, ExprId), [Define|_] = hipe_rtl:defines(Expr), case hipe_rtl:is_fpreg(Define) of true -> @@ -849,10 +850,10 @@ calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) -> _ -> case hipe_rtl:defines(Instr) of [] -> - calc_killed_expr_bb(Instrs, UseMap, AllExpr, KilledExprs); + calc_killed_expr_bb(Instrs, UseMap, AllExpr, IdMap, KilledExprs); [Define|_] -> NewKilledExprs = use_map_get_expr_uses(UseMap, Define), - calc_killed_expr_bb(Instrs, UseMap, AllExpr, + calc_killed_expr_bb(Instrs, UseMap, AllExpr, IdMap, ?SETS:union(NewKilledExprs, KilledExprs)) end end. diff --git a/lib/hipe/tools/Makefile b/lib/hipe/tools/Makefile index 0eaa3a7b05..f90d3c9f70 100644 --- a/lib/hipe/tools/Makefile +++ b/lib/hipe/tools/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2002-2010. All Rights Reserved. +# Copyright Ericsson AB 2002-2011. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -42,7 +42,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN) # ---------------------------------------------------- # Target Specs # ---------------------------------------------------- -MODULES = hipe_tool hipe_profile hipe_ceach hipe_jit +MODULES = hipe_tool hipe_profile hipe_jit # hipe_timer HRL_FILES= diff --git a/lib/hipe/tools/hipe_ceach.erl b/lib/hipe/tools/hipe_ceach.erl deleted file mode 100644 index b29615e169..0000000000 --- a/lib/hipe/tools/hipe_ceach.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% -*- erlang-indent-level: 2 -*- -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Copyright (c) 2001 by Erik Johansson. All Rights Reserved -%% ==================================================================== -%% Module : hipe_ceach -%% Purpose : Compile each function in a module, possibly applying a -%% fun between each compilation. Useful for bug hunting by -%% pinpointing a function that when compiled causes a bug. -%% Notes : -%% History : * 2001-12-11 Erik Johansson ([email protected]): Created. -%% ==================================================================== -%% Exports : -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - --module(hipe_ceach). - --export([c/1, c/2, c/3]). - --include("../main/hipe.hrl"). - -%%--------------------------------------------------------------------- - --spec c(atom()) -> 'ok'. - -c(M) -> - lists:foreach(fun({F,A}) -> comp(M, F, A) end, - M:module_info(functions)). - --spec c(atom(), comp_options()) -> 'ok'. - -c(M, Opts) -> - lists:foreach(fun({F,A}) -> comp(M, F, A, Opts) end, - M:module_info(functions)). - --spec c(atom(), comp_options(), fun(() -> any())) -> 'ok'. - -c(M, Opts, Fn) -> - lists:foreach(fun({F,A}) -> comp(M, F, A, Opts), Fn() end, - M:module_info(functions)). - --spec comp(atom(), atom(), arity()) -> 'ok'. - -comp(M, F, A) -> - io:format("~w:~w/~w... ", [M, F, A]), - MFA = {M, F, A}, - {ok, MFA} = hipe:c(MFA), - io:format("OK\n"). - --spec comp(atom(), atom(), arity(), comp_options()) -> 'ok'. - -comp(M, F, A, Opts) -> - io:format("~w:~w/~w... ", [M, F, A]), - MFA = {M, F, A}, - {ok, MFA} = hipe:c(MFA, Opts), - io:format("OK\n"). diff --git a/lib/hipe/tools/hipe_profile.erl b/lib/hipe/tools/hipe_profile.erl index 7566acb8f4..ea6b1fb42c 100644 --- a/lib/hipe/tools/hipe_profile.erl +++ b/lib/hipe/tools/hipe_profile.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% Copyright Ericsson AB 2002-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -89,7 +89,7 @@ calls() -> %% F(), %% %% Get result. %% R = res(), -%% %% Turn of profiling. +%% %% Turn off profiling. %% prof_off(), %% R. diff --git a/lib/hipe/util/hipe_dot.erl b/lib/hipe/util/hipe_dot.erl index d6ef801c88..e4a47ae0c4 100755..100644 --- a/lib/hipe/util/hipe_dot.erl +++ b/lib/hipe/util/hipe_dot.erl @@ -2,7 +2,7 @@ %%% %%% %CopyrightBegin% %%% -%%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %%% %%% The contents of this file are subject to the Erlang Public License, %%% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index 65e04ff7fa..347a0336cd 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.8.1 +HIPE_VSN = 3.9 |