aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe')
-rw-r--r--lib/hipe/arm/hipe_arm_pp.erl17
-rw-r--r--lib/hipe/cerl/cerl_closurean.erl14
-rw-r--r--lib/hipe/cerl/cerl_messagean.erl16
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl282
-rw-r--r--lib/hipe/cerl/erl_types.erl656
-rw-r--r--lib/hipe/doc/src/notes.xml85
-rw-r--r--lib/hipe/flow/hipe_dominators.erl12
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl29
-rw-r--r--lib/hipe/icode/hipe_icode.erl32
-rw-r--r--lib/hipe/icode/hipe_icode_exceptions.erl10
-rw-r--r--lib/hipe/icode/hipe_icode_type.erl20
-rw-r--r--lib/hipe/main/hipe.erl4
-rw-r--r--lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl52
-rw-r--r--lib/hipe/rtl/hipe_rtl_primops.erl22
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl4
-rw-r--r--lib/hipe/util/hipe_digraph.erl12
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/hipe/x86/hipe_x86_spill_restore.erl40
18 files changed, 875 insertions, 434 deletions
diff --git a/lib/hipe/arm/hipe_arm_pp.erl b/lib/hipe/arm/hipe_arm_pp.erl
index 7ce8421994..c4dde31188 100644
--- a/lib/hipe/arm/hipe_arm_pp.erl
+++ b/lib/hipe/arm/hipe_arm_pp.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2010. 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%
%%
@@ -246,6 +246,11 @@ stop_suffix(StOp) ->
'strb' -> "b"
end.
+imm8m_decode(Value, 0) ->
+ Value;
+imm8m_decode(Value, Rot) ->
+ (Value bsr (2 * Rot)) bor (Value bsl (2 * (16 - Rot))).
+
pp_temp(Dev, Temp=#arm_temp{reg=Reg, type=Type}) ->
case hipe_arm:temp_is_precoloured(Temp) of
true ->
@@ -292,7 +297,7 @@ pp_am1(Dev, Am1) ->
io:format(Dev, "#~w", [Imm5])
end;
{Imm8,Imm4} ->
- io:format(Dev, "#~w, 2*~w", [Imm8,Imm4])
+ io:format(Dev, "#~s", [to_hex(imm8m_decode(Imm8, Imm4))])
end.
pp_am2(Dev, #am2{src=Src,sign=Sign,offset=Am2Offset}) ->
diff --git a/lib/hipe/cerl/cerl_closurean.erl b/lib/hipe/cerl/cerl_closurean.erl
index 12771668ac..021acd5b35 100644
--- a/lib/hipe/cerl/cerl_closurean.erl
+++ b/lib/hipe/cerl/cerl_closurean.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2003-2010. 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%
%%
%% =====================================================================
@@ -808,7 +808,7 @@ take_work({Queue0, Set0}) ->
is_escape_op(match_fail, 1) -> false;
is_escape_op(F, A) when is_atom(F), is_integer(A) -> true.
--spec is_escape_op(module(), atom(), arity()) -> boolean().
+-spec is_escape_op(atom(), atom(), arity()) -> boolean().
is_escape_op(erlang, error, 1) -> false;
is_escape_op(erlang, error, 2) -> false;
@@ -825,7 +825,7 @@ is_escape_op(M, F, A) when is_atom(M), is_atom(F), is_integer(A) -> true.
is_literal_op(match_fail, 1) -> true;
is_literal_op(F, A) when is_atom(F), is_integer(A) -> false.
--spec is_literal_op(module(), atom(), arity()) -> boolean().
+-spec is_literal_op(atom(), atom(), arity()) -> boolean().
is_literal_op(erlang, '+', 2) -> true;
is_literal_op(erlang, '-', 2) -> true;
diff --git a/lib/hipe/cerl/cerl_messagean.erl b/lib/hipe/cerl/cerl_messagean.erl
index 0753376e7d..6dd93adaa3 100644
--- a/lib/hipe/cerl/cerl_messagean.erl
+++ b/lib/hipe/cerl/cerl_messagean.erl
@@ -1,19 +1,19 @@
%% =====================================================================
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2010. 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%
%%
%% Message analysis of Core Erlang programs.
@@ -1043,7 +1043,7 @@ get_deps(L, Dep) ->
%% is_escape_op(_F, _A) -> [].
--spec is_escape_op(module(), atom(), arity()) -> [arity()].
+-spec is_escape_op(atom(), atom(), arity()) -> [arity()].
is_escape_op(erlang, '!', 2) -> [2];
is_escape_op(erlang, send, 2) -> [2];
@@ -1064,7 +1064,7 @@ is_escape_op(_M, _F, _A) -> [].
is_imm_op(match_fail, 1) -> true;
is_imm_op(_, _) -> false.
--spec is_imm_op(module(), atom(), arity()) -> boolean().
+-spec is_imm_op(atom(), atom(), arity()) -> boolean().
is_imm_op(erlang, self, 0) -> true;
is_imm_op(erlang, '=:=', 2) -> true;
@@ -1102,4 +1102,4 @@ is_imm_op(erlang, throw, 1) -> true;
is_imm_op(erlang, exit, 1) -> true;
is_imm_op(erlang, error, 1) -> true;
is_imm_op(erlang, error, 2) -> true;
-is_imm_op(_, _, _) -> false.
+is_imm_op(_M, _F, _A) -> false.
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 38342870e5..6eeeab3610 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -143,6 +143,51 @@ type(M, F, A) ->
-spec type(atom(), atom(), arity(), [erl_types:erl_type()]) -> erl_types:erl_type().
+%%-- binary -------------------------------------------------------------------
+type(binary, at, 2, Xs) ->
+ strict(arg_types(binary, at, 2), Xs, fun(_) -> t_integer() end);
+type(binary, bin_to_list, Arity, Xs) when 1 =< Arity, Arity =< 3 ->
+ strict(arg_types(binary, bin_to_list, Arity), Xs,
+ fun(_) -> t_list(t_integer()) end);
+type(binary, compile_pattern, 1, Xs) ->
+ strict(arg_types(binary, compile_pattern, 1), Xs,
+ fun(_) -> t_tuple([t_atom(bm),t_binary()]) end);
+type(binary, copy, Arity, Xs) when Arity =:= 1; Arity =:= 2 ->
+ strict(arg_types(binary, copy, Arity), Xs,
+ fun(_) -> t_binary() end);
+type(binary, decode_unsigned, Arity, Xs) when Arity =:= 1; Arity =:= 2 ->
+ strict(arg_types(binary, decode_unsigned, Arity), Xs,
+ fun(_) -> t_non_neg_integer() end);
+type(binary, encode_unsigned, Arity, Xs) when Arity =:= 1; Arity =:= 2 ->
+ strict(arg_types(binary, encode_unsigned, Arity), Xs,
+ fun(_) -> t_binary() end);
+type(binary, first, 1, Xs) ->
+ strict(arg_types(binary, first, 1), Xs, fun(_) -> t_non_neg_integer() end);
+type(binary, last, 1, Xs) ->
+ strict(arg_types(binary, last, 1), Xs, fun(_) -> t_non_neg_integer() end);
+type(binary, list_to_bin, 1, Xs) ->
+ type(erlang, list_to_binary, 1, Xs);
+type(binary, longest_common_prefix, 1, Xs) ->
+ strict(arg_types(binary, longest_common_prefix, 1), Xs,
+ fun(_) -> t_integer() end);
+type(binary, longest_common_suffix, 1, Xs) ->
+ strict(arg_types(binary, longest_common_suffix, 1), Xs,
+ fun(_) -> t_integer() end);
+type(binary, match, Arity, Xs) when Arity =:= 2; Arity =:= 3 ->
+ strict(arg_types(binary, match, Arity), Xs,
+ fun(_) ->
+ t_sup(t_atom('nomatch'), t_binary_canonical_part())
+ end);
+type(binary, matches, Arity, Xs) when Arity =:= 2; Arity =:= 3 ->
+ strict(arg_types(binary, matches, Arity), Xs,
+ fun(_) -> t_list(t_binary_canonical_part()) end);
+type(binary, part, 2, Xs) ->
+ type(erlang, binary_part, 2, Xs);
+type(binary, part, 3, Xs) ->
+ type(erlang, binary_part, 3, Xs);
+type(binary, referenced_byte_size, 1, Xs) ->
+ strict(arg_types(binary, referenced_byte_size, 1), Xs,
+ fun(_) -> t_non_neg_integer() end);
%%-- code ---------------------------------------------------------------------
type(code, add_path, 1, Xs) ->
strict(arg_types(code, add_path, 1), Xs,
@@ -665,6 +710,14 @@ type(erlang, 'bnot', 1, Xs) ->
%% strict(arg_types(erlang, 'bnot', 1), Xs, fun (_) -> t_integer() end);
type(erlang, abs, 1, Xs) ->
strict(arg_types(erlang, abs, 1), Xs, fun ([X]) -> X end);
+type(erlang, adler32, 1, Xs) ->
+ strict(arg_types(erlang, adler32, 1), Xs, fun (_) -> t_adler32() end);
+type(erlang, adler32, 2, Xs) ->
+ strict(arg_types(erlang, adler32, 2), Xs, fun (_) -> t_adler32() end);
+type(erlang, adler32_combine, 3, Xs) ->
+ strict(arg_types(erlang, adler32_combine, 3), Xs,
+ fun (_) -> t_adler32() end);
+type(erlang, append, 2, Xs) -> type(erlang, '++', 2, Xs); % alias
type(erlang, append_element, 2, Xs) ->
strict(arg_types(erlang, append_element, 2), Xs, fun (_) -> t_tuple() end);
type(erlang, apply, 2, Xs) ->
@@ -683,6 +736,10 @@ type(erlang, atom_to_binary, 2, Xs) ->
strict(arg_types(erlang, atom_to_binary, 2), Xs, fun (_) -> t_binary() end);
type(erlang, atom_to_list, 1, Xs) ->
strict(arg_types(erlang, atom_to_list, 1), Xs, fun (_) -> t_string() end);
+type(erlang, binary_part, 2, Xs) ->
+ strict(arg_types(erlang, binary_part, 2), Xs, fun (_) -> t_binary() end);
+type(erlang, binary_part, 3, Xs) ->
+ strict(arg_types(erlang, binary_part, 3), Xs, fun (_) -> t_binary() end);
type(erlang, binary_to_atom, 2, Xs) ->
strict(arg_types(erlang, binary_to_atom, 2), Xs, fun (_) -> t_atom() end);
type(erlang, binary_to_existing_atom, 2, Xs) ->
@@ -726,11 +783,11 @@ type(erlang, check_process_code, 2, Xs) ->
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_integer() end);
+ strict(arg_types(erlang, crc32, 1), Xs, fun (_) -> t_crc32() end);
type(erlang, crc32, 2, Xs) ->
- strict(arg_types(erlang, crc32, 2), Xs, fun (_) -> t_integer() end);
+ strict(arg_types(erlang, crc32, 2), Xs, fun (_) -> t_crc32() end);
type(erlang, crc32_combine, 3, Xs) ->
- strict(arg_types(erlang, crc32_combine, 3), Xs, fun (_) -> t_integer() end);
+ strict(arg_types(erlang, crc32_combine, 3), Xs, fun (_) -> t_crc32() end);
type(erlang, date, 0, _) ->
t_date();
type(erlang, decode_packet, 3, Xs) ->
@@ -752,6 +809,10 @@ type(erlang, demonitor, 2, Xs) ->
type(erlang, disconnect_node, 1, Xs) ->
strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_boolean() end);
type(erlang, display, 1, _) -> t_atom('true');
+type(erlang, display_string, 1, Xs) ->
+ strict(arg_types(erlang, display_string, 1), Xs, fun(_) -> t_atom('true') end);
+type(erlang, display_nl, 0, _) ->
+ t_atom('true');
type(erlang, dist_exit, 3, Xs) ->
strict(arg_types(erlang, dist_exit, 3), Xs, fun (_) -> t_atom('true') end);
type(erlang, element, 2, Xs) ->
@@ -802,6 +863,8 @@ type(erlang, fun_to_list, 1, Xs) ->
type(erlang, garbage_collect, 0, _) -> t_atom('true');
type(erlang, garbage_collect, 1, Xs) ->
strict(arg_types(erlang, garbage_collect, 1), Xs, fun (_) -> t_boolean() end);
+type(erlang, garbage_collect_message_area, 0, _) ->
+ t_boolean();
type(erlang, get, 0, _) -> t_list(t_tuple(2));
type(erlang, get, 1, _) -> t_any(); % | t_atom('undefined')
type(erlang, get_cookie, 0, _) -> t_atom(); % | t_atom('nocookie')
@@ -851,6 +914,9 @@ type(erlang, hd, 1, Xs) ->
type(erlang, integer_to_list, 1, Xs) ->
strict(arg_types(erlang, integer_to_list, 1), Xs,
fun (_) -> t_string() end);
+type(erlang, integer_to_list, 2, Xs) ->
+ strict(arg_types(erlang, integer_to_list, 2), Xs,
+ fun (_) -> t_string() end);
type(erlang, info, 1, Xs) -> type(erlang, system_info, 1, Xs); % alias
type(erlang, iolist_size, 1, Xs) ->
strict(arg_types(erlang, iolist_size, 1), Xs,
@@ -1056,15 +1122,26 @@ type(erlang, list_to_float, 1, Xs) ->
type(erlang, list_to_integer, 1, Xs) ->
strict(arg_types(erlang, list_to_integer, 1), Xs,
fun (_) -> t_integer() end);
+type(erlang, list_to_integer, 2, Xs) ->
+ strict(arg_types(erlang, list_to_integer, 2), Xs,
+ fun (_) -> t_integer() end);
type(erlang, list_to_pid, 1, Xs) ->
strict(arg_types(erlang, list_to_pid, 1), Xs, fun (_) -> t_pid() end);
type(erlang, list_to_tuple, 1, Xs) ->
strict(arg_types(erlang, list_to_tuple, 1), Xs, fun (_) -> t_tuple() end);
-type(erlang, loaded, 0, _) ->
- t_list(t_atom());
type(erlang, load_module, 2, Xs) ->
strict(arg_types(erlang, load_module, 2), Xs,
fun ([Mod,_Bin]) -> t_code_load_return(Mod) end);
+type(erlang, load_nif, 2, Xs) ->
+ strict(arg_types(erlang, load_nif, 2), Xs,
+ fun (_) ->
+ Reason = t_atoms(['load_failed', 'bad_lib', 'load',
+ 'reload', 'upgrade', 'old_code']),
+ RsnPair = t_tuple([Reason, t_string()]),
+ t_sup(t_atom('ok'), t_tuple([t_atom('error'), RsnPair]))
+ end);
+type(erlang, loaded, 0, _) ->
+ t_list(t_atom());
type(erlang, localtime, 0, Xs) ->
type(erlang, universaltime, 0, Xs); % same
type(erlang, localtime_to_universaltime, 1, Xs) ->
@@ -1141,6 +1218,10 @@ type(erlang, monitor_node, 2, Xs) ->
type(erlang, monitor_node, 3, Xs) ->
strict(arg_types(erlang, monitor_node, 3), Xs,
fun (_) -> t_atom('true') end);
+type(erlang, nif_error, 1, _) ->
+ t_any();
+type(erlang, nif_error, 2, Xs) ->
+ strict(arg_types(erlang, nif_error, 2), Xs, fun (_) -> t_any() end);
type(erlang, node, 0, _) -> t_node();
type(erlang, node, 1, Xs) ->
strict(arg_types(erlang, node, 1), Xs, fun (_) -> t_node() end);
@@ -1159,8 +1240,8 @@ type(erlang, phash2, 2, Xs) ->
strict(arg_types(erlang, phash2, 2), Xs, fun (_) -> t_non_neg_integer() end);
type(erlang, pid_to_list, 1, Xs) ->
strict(arg_types(erlang, pid_to_list, 1), Xs, fun (_) -> t_string() end);
-type(erlang, port_call, 3, Xs) ->
- strict(arg_types(erlang, port_call, 3), Xs, fun (_) -> t_any() end);
+type(erlang, port_call, Arity, Xs) when Arity =:= 2; Arity =:= 3 ->
+ strict(arg_types(erlang, port_call, Arity), Xs, fun (_) -> t_any() end);
type(erlang, port_close, 1, Xs) ->
strict(arg_types(erlang, port_close, 1), Xs,
fun (_) -> t_atom('true') end);
@@ -1489,6 +1570,7 @@ type(erlang, statistics, 1, Xs) ->
T_statistics_1
end
end);
+type(erlang, subtract, 2, Xs) -> type(erlang, '--', 2, Xs); % alias
type(erlang, suspend_process, 1, Xs) ->
strict(arg_types(erlang, suspend_process, 1), Xs,
fun (_) -> t_atom('true') end);
@@ -1556,7 +1638,6 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_integer()])]));
['allocator'] ->
t_tuple([t_sup([t_atom('undefined'),
- t_atom('elib_malloc'),
t_atom('glibc')]),
t_list(t_integer()),
t_list(t_atom()),
@@ -1577,11 +1658,10 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['dist_ctrl'] ->
t_list(t_tuple([t_atom(), t_sup([t_pid(), t_port])]));
- ['elib_malloc'] ->
- t_sup([t_atom('false'),
- t_list(t_tuple([t_atom(), t_any()]))]);
+ %% elib_malloc is intentionally not included,
+ %% because it scheduled for removal in R15.
['endian'] ->
- t_sup([t_atom('big'), t_atom('little')]);
+ t_endian();
['fullsweep_after'] ->
t_tuple([t_atom('fullsweep_after'), t_non_neg_integer()]);
['garbage_collection'] ->
@@ -1593,9 +1673,8 @@ type(erlang, system_info, 1, Xs) ->
['heap_type'] ->
t_sup([t_atom('private'), t_atom('hybrid')]);
['hipe_architecture'] ->
- t_sup([t_atom('amd64'), t_atom('arm'),
- t_atom('powerpc'), t_atom('undefined'),
- t_atom('ultrasparc'), t_atom('x86')]);
+ t_atoms(['amd64', 'arm', 'powerpc', 'ppc64',
+ 'undefined', 'ultrasparc', 'x86']);
['info'] ->
t_binary();
['internal_cpu_topology'] -> %% Undocumented internal feature
@@ -1771,11 +1850,21 @@ type(erts_debug, disassemble, 1, Xs) ->
fun (_) -> t_sup([t_atom('false'),
t_atom('undef'),
t_tuple([t_integer(), t_binary(), t_mfa()])]) end);
+type(erts_debug, display, 1, _) ->
+ t_string();
type(erts_debug, dist_ext_to_term, 2, Xs) ->
strict(arg_types(erts_debug, dist_ext_to_term, 2), Xs,
fun (_) -> t_any() end);
+type(erts_debug, dump_monitors, 1, Xs) ->
+ strict(arg_types(erts_debug, dump_monitors, 1), Xs,
+ fun(_) -> t_atom('true') end);
+type(erts_debug, dump_links, 1, Xs) ->
+ strict(arg_types(erts_debug, dump_links, 1), Xs,
+ fun(_) -> t_atom('true') end);
type(erts_debug, flat_size, 1, Xs) ->
strict(arg_types(erts_debug, flat_size, 1), Xs, fun (_) -> t_integer() end);
+type(erts_debug, get_internal_state, 1, _) ->
+ t_any();
type(erts_debug, lock_counters, 1, Xs) ->
strict(arg_types(erts_debug, lock_counters, 1), Xs,
fun ([Arg]) ->
@@ -1796,6 +1885,8 @@ type(erts_debug, lock_counters, 1, Xs) ->
end);
type(erts_debug, same, 2, Xs) ->
strict(arg_types(erts_debug, same, 2), Xs, fun (_) -> t_boolean() end);
+type(erts_debug, set_internal_state, 2, _) ->
+ t_any();
%%-- ets ----------------------------------------------------------------------
type(ets, all, 0, _) ->
t_list(t_tab());
@@ -2085,7 +2176,7 @@ type(hipe_bifs, set_native_address, 3, Xs) ->
strict(arg_types(hipe_bifs, set_native_address, 3), Xs,
fun (_) -> t_nil() end);
type(hipe_bifs, system_crc, 1, Xs) ->
- strict(arg_types(hipe_bifs, system_crc, 1), Xs, fun (_) -> t_integer() end);
+ strict(arg_types(hipe_bifs, system_crc, 1), Xs, fun (_) -> t_crc32() end);
type(hipe_bifs, term_to_word, 1, Xs) ->
strict(arg_types(hipe_bifs, term_to_word, 1), Xs,
fun (_) -> t_integer() end);
@@ -2244,8 +2335,7 @@ type(lists, flatten, 1, Xs) ->
t_list();
false ->
X2 = type(lists, flatten, 1, [t_inf(X1, t_list())]),
- t_sup(t_list(t_subtract(X1, t_list())),
- X2)
+ t_sup(t_list(t_subtract(X1, t_list())), X2)
end
end
end);
@@ -2256,10 +2346,20 @@ type(lists, flatmap, 2, Xs) ->
true -> t_nil();
false ->
case check_fun_application(F, [t_list_elements(List)]) of
- ok ->
- case t_is_cons(List) of
- true -> t_nonempty_list(t_list_elements(t_fun_range(F)));
- false -> t_list(t_list_elements(t_fun_range(F)))
+ ok ->
+ R = t_fun_range(F),
+ case t_is_nil(R) of
+ true -> t_nil();
+ false ->
+ Elems = t_list_elements(R),
+ case t_is_cons(List) of
+ true ->
+ case t_is_subtype(t_nil(), R) of
+ true -> t_list(Elems);
+ false -> t_nonempty_list(Elems)
+ end;
+ false -> t_list(Elems)
+ end
end;
error ->
case t_is_cons(List) of
@@ -3180,6 +3280,53 @@ arith(Op, X1, X2) ->
-spec arg_types(atom(), atom(), arity()) -> [erl_types:erl_type()] | 'unknown'.
+%%------- binary --------------------------------------------------------------
+arg_types(binary, at, 2) ->
+ [t_binary(), t_non_neg_integer()];
+arg_types(binary, bin_to_list, 1) ->
+ [t_binary()];
+arg_types(binary, bin_to_list, 2) ->
+ [t_binary(), t_binary_part()];
+arg_types(binary, bin_to_list, 3) ->
+ [t_binary(), t_integer(), t_non_neg_integer()];
+arg_types(binary, compile_pattern, 1) ->
+ [t_sup(t_binary(), t_list(t_binary()))];
+arg_types(binary, copy, 1) ->
+ [t_binary()];
+arg_types(binary, copy, 2) ->
+ [t_binary(), t_non_neg_integer()];
+arg_types(binary, decode_unsigned, 1) ->
+ [t_binary()];
+arg_types(binary, decode_unsigned, 2) ->
+ [t_binary(), t_endian()];
+arg_types(binary, encode_unsigned, 1) ->
+ [t_non_neg_integer()];
+arg_types(binary, encode_unsigned, 2) ->
+ [t_non_neg_integer(), t_endian()];
+arg_types(binary, first, 1) ->
+ [t_binary()];
+arg_types(binary, last, 1) ->
+ [t_binary()];
+arg_types(binary, list_to_bin, 1) ->
+ arg_types(erlang, list_to_binary, 1);
+arg_types(binary, longest_common_prefix, 1) ->
+ [t_list(t_binary())];
+arg_types(binary, longest_common_suffix, 1) ->
+ [t_list(t_binary())];
+arg_types(binary, match, 2) ->
+ [t_binary(), t_binary_pattern()];
+arg_types(binary, match, 3) ->
+ [t_binary(), t_binary_pattern(), t_binary_options()];
+arg_types(binary, matches, 2) ->
+ [t_binary(), t_binary_pattern()];
+arg_types(binary, matches, 3) ->
+ [t_binary(), t_binary_pattern(), t_binary_options()];
+arg_types(binary, part, 2) ->
+ arg_types(erlang, binary_part, 2);
+arg_types(binary, part, 3) ->
+ arg_types(erlang, binary_part, 3);
+arg_types(binary, referenced_byte_size, 1) ->
+ [t_binary()];
%%------- code ----------------------------------------------------------------
arg_types(code, add_path, 1) ->
[t_string()];
@@ -3361,6 +3508,14 @@ arg_types(erlang, 'bnot', 1) ->
[t_integer()];
arg_types(erlang, abs, 1) ->
[t_number()];
+arg_types(erlang, adler32, 1) ->
+ [t_iodata()];
+arg_types(erlang, adler32, 2) ->
+ [t_adler32(), t_iodata()];
+arg_types(erlang, adler32_combine, 3) ->
+ [t_adler32(), t_adler32(), t_non_neg_integer()];
+arg_types(erlang, append, 2) ->
+ arg_types(erlang, '++', 2);
arg_types(erlang, append_element, 2) ->
[t_tuple(), t_any()];
arg_types(erlang, apply, 2) ->
@@ -3374,6 +3529,10 @@ arg_types(erlang, atom_to_binary, 2) ->
[t_atom(), t_encoding_a2b()];
arg_types(erlang, atom_to_list, 1) ->
[t_atom()];
+arg_types(erlang, binary_part, 2) ->
+ [t_binary(), t_tuple([t_integer(),t_integer()])];
+arg_types(erlang, binary_part, 3) ->
+ [t_binary(), t_integer(), t_integer()];
arg_types(erlang, binary_to_atom, 2) ->
[t_binary(), t_encoding_a2b()];
arg_types(erlang, binary_to_existing_atom, 2) ->
@@ -3409,9 +3568,9 @@ arg_types(erlang, concat_binary, 1) ->
arg_types(erlang, crc32, 1) ->
[t_iodata()];
arg_types(erlang, crc32, 2) ->
- [t_integer(), t_iodata()];
+ [t_crc32(), t_iodata()];
arg_types(erlang, crc32_combine, 3) ->
- [t_integer(), t_integer(), t_integer()];
+ [t_crc32(), t_crc32(), t_non_neg_integer()];
arg_types(erlang, date, 0) ->
[];
arg_types(erlang, decode_packet, 3) ->
@@ -3426,6 +3585,10 @@ arg_types(erlang, disconnect_node, 1) ->
[t_node()];
arg_types(erlang, display, 1) ->
[t_any()];
+arg_types(erlang, display_nl, 0) ->
+ [];
+arg_types(erlang, display_string, 1) ->
+ [t_string()];
arg_types(erlang, dist_exit, 3) ->
[t_pid(), t_dist_exit(), t_sup(t_pid(), t_port())];
arg_types(erlang, element, 2) ->
@@ -3462,6 +3625,8 @@ arg_types(erlang, garbage_collect, 0) ->
[];
arg_types(erlang, garbage_collect, 1) ->
[t_pid()];
+arg_types(erlang, garbage_collect_message_area, 0) ->
+ [];
arg_types(erlang, get, 0) ->
[];
arg_types(erlang, get, 1) ->
@@ -3498,6 +3663,8 @@ arg_types(erlang, iolist_size, 1) ->
[t_sup(t_iolist(), t_binary())];
arg_types(erlang, integer_to_list, 1) ->
[t_integer()];
+arg_types(erlang, integer_to_list, 2) ->
+ [t_integer(), t_from_range(2, 36)];
arg_types(erlang, is_alive, 0) ->
[];
arg_types(erlang, is_atom, 1) ->
@@ -3558,14 +3725,18 @@ arg_types(erlang, list_to_float, 1) ->
[t_list(t_byte())];
arg_types(erlang, list_to_integer, 1) ->
[t_list(t_byte())];
+arg_types(erlang, list_to_integer, 2) ->
+ [t_list(t_byte()), t_from_range(2, 36)];
arg_types(erlang, list_to_pid, 1) ->
[t_string()];
arg_types(erlang, list_to_tuple, 1) ->
[t_list()];
-arg_types(erlang, loaded, 0) ->
- [];
arg_types(erlang, load_module, 2) ->
[t_atom(), t_binary()];
+arg_types(erlang, load_nif, 2) ->
+ [t_string(), t_any()];
+arg_types(erlang, loaded, 0) ->
+ [];
arg_types(erlang, localtime, 0) ->
[];
arg_types(erlang, localtime_to_universaltime, 1) ->
@@ -3608,6 +3779,10 @@ arg_types(erlang, monitor_node, 2) ->
[t_node(), t_boolean()];
arg_types(erlang, monitor_node, 3) ->
[t_node(), t_boolean(), t_list(t_atom('allow_passive_connect'))];
+arg_types(erlang, nif_error, 1) ->
+ [t_any()];
+arg_types(erlang, nif_error, 2) ->
+ [t_any(), t_list()];
arg_types(erlang, node, 0) ->
[];
arg_types(erlang, node, 1) ->
@@ -3648,6 +3823,8 @@ arg_types(erlang, phash2, 2) ->
[t_any(), t_pos_integer()];
arg_types(erlang, pid_to_list, 1) ->
[t_pid()];
+arg_types(erlang, port_call, 2) ->
+ [t_sup(t_port(), t_atom()), t_any()];
arg_types(erlang, port_call, 3) ->
[t_sup(t_port(), t_atom()), t_integer(), t_any()];
arg_types(erlang, port_close, 1) ->
@@ -3775,6 +3952,8 @@ arg_types(erlang, statistics, 1) ->
t_atom('run_queue'),
t_atom('runtime'),
t_atom('wall_clock')])];
+arg_types(erlang, subtract, 2) ->
+ arg_types(erlang, '--', 2);
arg_types(erlang, suspend_process, 1) ->
[t_pid()];
arg_types(erlang, suspend_process, 2) ->
@@ -3854,7 +4033,8 @@ arg_types(erlang, trace_info, 2) ->
t_atom('flags'), t_atom('tracer'),
%% while the following are items about a func
t_atom('traced'), t_atom('match_spec'), t_atom('meta'),
- t_atom('meta_match_spec'), t_atom('call_count'), t_atom('all')])];
+ t_atom('meta_match_spec'), t_atom('call_count'),
+ t_atom('call_time'), t_atom('all')])];
arg_types(erlang, trace_pattern, 2) ->
[t_sup(t_tuple([t_atom(), t_atom(), t_sup(t_arity(), t_atom('_'))]),
t_atom('on_load')),
@@ -3863,7 +4043,7 @@ arg_types(erlang, trace_pattern, 3) ->
arg_types(erlang, trace_pattern, 2) ++
[t_list(t_sup([t_atom('global'), t_atom('local'),
t_atom('meta'), t_tuple([t_atom('meta'), t_pid()]),
- t_atom('call_count')]))];
+ t_atom('call_count'), t_atom('call_time')]))];
arg_types(erlang, trunc, 1) ->
[t_number()];
arg_types(erlang, tuple_size, 1) ->
@@ -3897,10 +4077,18 @@ arg_types(erts_debug, breakpoint, 2) ->
[t_tuple([t_atom(), t_atom(), t_sup(t_integer(), t_atom('_'))]), t_boolean()];
arg_types(erts_debug, disassemble, 1) ->
[t_sup(t_mfa(), t_integer())];
+arg_types(erts_debug, display, 1) ->
+ [t_any()];
arg_types(erts_debug, dist_ext_to_term, 2) ->
[t_tuple(), t_binary()];
+arg_types(erts_debug, dump_monitors, 1) ->
+ [t_sup([t_pid(),t_atom()])];
+arg_types(erts_debug, dump_links, 1) ->
+ [t_sup([t_pid(),t_atom(),t_port()])];
arg_types(erts_debug, flat_size, 1) ->
[t_any()];
+arg_types(erts_debug, get_internal_state, 1) ->
+ [t_any()];
arg_types(erts_debug, lock_counters, 1) ->
[t_sup([t_atom(enabled),
t_atom(info),
@@ -3909,6 +4097,8 @@ arg_types(erts_debug, lock_counters, 1) ->
t_tuple([t_atom(process_locks), t_boolean()])])];
arg_types(erts_debug, same, 2) ->
[t_any(), t_any()];
+arg_types(erts_debug, set_internal_state, 2) ->
+ [t_any(), t_any()];
%%------- ets -----------------------------------------------------------------
arg_types(ets, all, 0) ->
[];
@@ -4089,7 +4279,7 @@ arg_types(hipe_bifs, call_count_off, 1) ->
arg_types(hipe_bifs, call_count_on, 1) ->
[t_mfa()];
arg_types(hipe_bifs, check_crc, 1) ->
- [t_integer()];
+ [t_crc32()];
arg_types(hipe_bifs, enter_code, 2) ->
[t_binary(), t_sup(t_nil(), t_tuple())];
arg_types(hipe_bifs, enter_sdesc, 1) ->
@@ -4133,7 +4323,7 @@ arg_types(hipe_bifs, set_funinfo_native_address, 3) ->
arg_types(hipe_bifs, set_native_address, 3) ->
[t_mfa(), t_integer(), t_boolean()];
arg_types(hipe_bifs, system_crc, 1) ->
- [t_integer()];
+ [t_crc32()];
arg_types(hipe_bifs, term_to_word, 1) ->
[t_any()];
arg_types(hipe_bifs, update_code_size, 3) ->
@@ -4447,6 +4637,30 @@ t_httppacket() ->
t_sup([t_HttpRequest(), t_HttpResponse(),
t_HttpHeader(), t_atom('http_eoh'), t_HttpError()]).
+t_endian() ->
+ t_sup([t_atom('big'), t_atom('little')]).
+
+%% =====================================================================
+%% Types for the binary module
+%% =====================================================================
+
+t_binary_part() ->
+ t_tuple([t_non_neg_integer(),t_integer()]).
+
+t_binary_canonical_part() ->
+ t_tuple([t_non_neg_integer(),t_non_neg_integer()]).
+
+t_binary_pattern() ->
+ t_sup([t_binary(),
+ t_list(t_binary()),
+ t_binary_compiled_pattern()]).
+
+t_binary_compiled_pattern() ->
+ t_tuple([t_atom('cp'),t_binary()]).
+
+t_binary_options() ->
+ t_list(t_tuple([t_atom('scope'),t_binary_part()])).
+
%% =====================================================================
%% HTTP types documented in R12B-4
%% =====================================================================
@@ -4529,12 +4743,18 @@ t_code_loaded_fname_or_status() ->
%% These are used for the built-in functions of 'erlang'
%% =====================================================================
+t_adler32() ->
+ t_non_neg_integer().
+
+t_crc32() ->
+ t_non_neg_integer().
+
t_decode_packet_option() ->
t_sup([t_tuple([t_atom('packet_size'), t_non_neg_integer()]),
t_tuple([t_atom('line_length'), t_non_neg_integer()])]).
t_decode_packet_type() ->
- t_sup(t_inet_setoption_packettype(), t_atom('httph')).
+ t_sup([t_inet_setoption_packettype(), t_atom('httph'), t_atom('httph_bin')]).
t_dist_exit() ->
t_sup([t_atom('kill'), t_atom('noconnection'), t_atom('normal')]).
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index b4d80d359a..9bc56c99ff 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -178,7 +178,7 @@
t_remote/3,
t_string/0,
t_struct_from_opaque/2,
- t_solve_remote/2,
+ t_solve_remote/3,
t_subst/2,
t_subtract/2,
t_subtract_list/2,
@@ -205,11 +205,14 @@
t_var_name/1,
%% t_assign_variables_to_subtype/2,
type_is_defined/3,
+ record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
- lift_list_to_pos_empty/1
+ lift_list_to_pos_empty/1,
+ is_erl_type/1
]).
%%-define(DO_ERL_TYPES_TEST, true).
+-compile({no_auto_import,[min/2,max/2]}).
-ifdef(DO_ERL_TYPES_TEST).
-export([test/0]).
@@ -221,6 +224,8 @@
-export([t_is_identifier/1]).
-endif.
+-export_type([erl_type/0]).
+
%%=============================================================================
%%
%% Definition of the type structure
@@ -299,7 +304,7 @@
%% Auxiliary types and convenient macros
%%
--type parse_form() :: {atom(), _, _} | {atom(), _, _, _}. %% XXX: Temporarily
+-type parse_form() :: {atom(), _, _} | {atom(), _, _, _} | {'op', _, _, _, _}. %% XXX: Temporarily
-type rng_elem() :: 'pos_inf' | 'neg_inf' | integer().
-record(int_set, {set :: [integer()]}).
@@ -322,7 +327,7 @@
-define(nil, #c{tag=?nil_tag}).
-define(nonempty_list(Types, Term),?list(Types, Term, ?nonempty_qual)).
-define(number(Set, Qualifier), #c{tag=?number_tag, elements=Set,
- qualifier=Qualifier}.
+ qualifier=Qualifier}).
-define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}).
-define(product(Types), #c{tag=?product_tag, elements=Types}).
-define(remote(RemTypes), #c{tag=?remote_tag, elements=RemTypes}).
@@ -398,7 +403,8 @@ t_is_none(_) -> false.
-spec t_opaque(module(), atom(), [_], erl_type()) -> erl_type().
t_opaque(Mod, Name, Args, Struct) ->
- ?opaque(set_singleton(#opaque{mod=Mod, name=Name, args=Args, struct=Struct})).
+ O = #opaque{mod = Mod, name = Name, args = Args, struct = Struct},
+ ?opaque(set_singleton(O)).
-spec t_is_opaque(erl_type()) -> boolean().
@@ -427,7 +433,7 @@ t_opaque_structure(?opaque(Elements)) ->
t_opaque_module(?opaque(Elements)) ->
case ordsets:size(Elements) of
1 ->
- [#opaque{mod=Module}] = ordsets:to_list(Elements),
+ [#opaque{mod = Module}] = ordsets:to_list(Elements),
Module;
_ -> throw({error, "Unexpected multiple opaque types"})
end.
@@ -631,7 +637,7 @@ t_unopaque_on_mismatch(GenType, Type, Opaques) ->
case t_inf(GenType, Type) of
?none ->
Unopaqued = t_unopaque(Type, Opaques),
- %% Unions might be a problem, must investigate.
+ %% XXX: Unions might be a problem, must investigate.
case t_inf(GenType, Unopaqued) of
?none -> Type;
_ -> Unopaqued
@@ -643,12 +649,12 @@ t_unopaque_on_mismatch(GenType, Type, Opaques) ->
module_builtin_opaques(Module) ->
[O || O <- all_opaque_builtins(), t_opaque_module(O) =:= Module].
-
+
%%-----------------------------------------------------------------------------
-%% Remote types
-%% These types are used for preprocessing they should never reach the analysis stage
+%% Remote types: these types are used for preprocessing;
+%% they should never reach the analysis stage.
--spec t_remote(module(), atom(), [_]) -> erl_type().
+-spec t_remote(atom(), atom(), [erl_type()]) -> erl_type().
t_remote(Mod, Name, Args) ->
?remote(set_singleton(#remote{mod = Mod, name = Name, args = Args})).
@@ -658,126 +664,132 @@ t_remote(Mod, Name, Args) ->
t_is_remote(?remote(_)) -> true;
t_is_remote(_) -> false.
--spec t_solve_remote(erl_type(), dict()) -> erl_type().
+-spec t_solve_remote(erl_type(), set(), dict()) -> erl_type().
-t_solve_remote(Type , Records) ->
- {RT, _RR} = t_solve_remote(Type, Records, []),
+t_solve_remote(Type, ExpTypes, Records) ->
+ {RT, _RR} = t_solve_remote(Type, ExpTypes, Records, []),
RT.
-t_solve_remote(?function(Domain, Range), R, C) ->
- {RT1, RR1} = t_solve_remote(Domain, R, C),
- {RT2, RR2} = t_solve_remote(Range, R, C),
+t_solve_remote(?function(Domain, Range), ET, R, C) ->
+ {RT1, RR1} = t_solve_remote(Domain, ET, R, C),
+ {RT2, RR2} = t_solve_remote(Range, ET, R, C),
{?function(RT1, RT2), RR1 ++ RR2};
-t_solve_remote(?list(Types, Term, Size), R, C) ->
- {RT, RR} = t_solve_remote(Types, R, C),
+t_solve_remote(?list(Types, Term, Size), ET, R, C) ->
+ {RT, RR} = t_solve_remote(Types, ET, R, C),
{?list(RT, Term, Size), RR};
-t_solve_remote(?product(Types), R, C) ->
- {RL, RR} = list_solve_remote(Types, R, C),
+t_solve_remote(?product(Types), ET, R, C) ->
+ {RL, RR} = list_solve_remote(Types, ET, R, C),
{?product(RL), RR};
-t_solve_remote(?opaque(Set), R, C) ->
+t_solve_remote(?opaque(Set), ET, R, C) ->
List = ordsets:to_list(Set),
- {NewList, RR} = opaques_solve_remote(List, R, C),
+ {NewList, RR} = opaques_solve_remote(List, ET, R, C),
{?opaque(ordsets:from_list(NewList)), RR};
-t_solve_remote(?tuple(?any, _, _) = T, _R, _C) -> {T, []};
-t_solve_remote(?tuple(Types, Arity, Tag), R, C) ->
- {RL, RR} = list_solve_remote(Types, R, C),
+t_solve_remote(?tuple(?any, _, _) = T, _ET, _R, _C) -> {T, []};
+t_solve_remote(?tuple(Types, Arity, Tag), ET, R, C) ->
+ {RL, RR} = list_solve_remote(Types, ET, R, C),
{?tuple(RL, Arity, Tag), RR};
-t_solve_remote(?tuple_set(Set), R, C) ->
- {NewSet, RR} = tuples_solve_remote(Set, R, C),
+t_solve_remote(?tuple_set(Set), ET, R, C) ->
+ {NewSet, RR} = tuples_solve_remote(Set, ET, R, C),
{?tuple_set(NewSet), RR};
-t_solve_remote(?remote(Set), R, C) ->
+t_solve_remote(?remote(Set), ET, R, C) ->
RemoteList = ordsets:to_list(Set),
- {RL, RR} = list_solve_remote_type(RemoteList, R, C),
+ {RL, RR} = list_solve_remote_type(RemoteList, ET, R, C),
{t_sup(RL), RR};
-t_solve_remote(?union(List), R, C) ->
- {RL, RR} = list_solve_remote(List, R, C),
+t_solve_remote(?union(List), ET, R, C) ->
+ {RL, RR} = list_solve_remote(List, ET, R, C),
{t_sup(RL), RR};
-t_solve_remote(T, _R, _C) -> {T, []}.
+t_solve_remote(T, _ET, _R, _C) -> {T, []}.
t_solve_remote_type(#remote{mod = RemMod, name = Name, args = Args} = RemType,
- R, C) ->
+ ET, R, C) ->
+ ArgsLen = length(Args),
case dict:find(RemMod, R) of
error ->
- Msg = io_lib:format("Cannot locate module ~w to "
- "resolve the remote type: ~w:~w()~n",
- [RemMod, RemMod, Name]),
- throw({error, Msg});
+ self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
+ {t_any(), []};
{ok, RemDict} ->
- case lookup_type(Name, RemDict) of
- {type, {_Mod, Type, ArgNames}} when length(Args) =:= length(ArgNames) ->
- {NewType, NewCycle, NewRR} =
- case unfold(RemType, C) of
- true ->
- List = lists:zip(ArgNames, Args),
- TmpVarDict = dict:from_list(List),
- {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
- false -> {t_any(), C, [RemType]}
- end,
- {RT, RR} = t_solve_remote(NewType, R, NewCycle),
- RetRR = NewRR ++ RR,
- RT1 =
- case lists:member(RemType, RetRR) of
- true -> t_limit(RT, ?REC_TYPE_LIMIT);
- false -> RT
- end,
- {RT1, RetRR};
- {opaque, {Mod, Type, ArgNames}} when length(Args) =:= length(ArgNames) ->
- List = lists:zip(ArgNames, Args),
- TmpVarDict = dict:from_list(List),
- {Rep, NewCycle, NewRR} =
- case unfold(RemType, C) of
- true -> {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
- false -> {t_any(), C, [RemType]}
- end,
- {NewRep, RR} = t_solve_remote(Rep, R, NewCycle),
- RetRR = NewRR ++ RR,
- RT1 =
- case lists:member(RemType, RetRR) of
- true -> t_limit(NewRep, ?REC_TYPE_LIMIT);
- false -> NewRep
- end,
- {t_from_form({opaque, -1, Name, {Mod, Args, RT1}},
- RemDict, TmpVarDict),
- RetRR};
- {type, _} ->
- Msg = io_lib:format("Unknown remote type ~w\n", [Name]),
- throw({error, Msg});
- {opaque, _} ->
- Msg = io_lib:format("Unknown remote opaque type ~w\n", [Name]),
- throw({error, Msg});
- error ->
- Msg = io_lib:format("Unable to find remote type ~w:~w()\n",
- [RemMod, Name]),
- throw({error, Msg})
+ MFA = {RemMod, Name, ArgsLen},
+ case sets:is_element(MFA, ET) of
+ true ->
+ case lookup_type(Name, RemDict) of
+ {type, {_Mod, Type, ArgNames}} when ArgsLen =:= length(ArgNames) ->
+ {NewType, NewCycle, NewRR} =
+ case unfold(RemType, C) of
+ true ->
+ List = lists:zip(ArgNames, Args),
+ TmpVarDict = dict:from_list(List),
+ {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
+ false -> {t_any(), C, [RemType]}
+ end,
+ {RT, RR} = t_solve_remote(NewType, ET, R, NewCycle),
+ RetRR = NewRR ++ RR,
+ RT1 =
+ case lists:member(RemType, RetRR) of
+ true -> t_limit(RT, ?REC_TYPE_LIMIT);
+ false -> RT
+ end,
+ {RT1, RetRR};
+ {opaque, {Mod, Type, ArgNames}} when ArgsLen =:= length(ArgNames) ->
+ List = lists:zip(ArgNames, Args),
+ TmpVarDict = dict:from_list(List),
+ {Rep, NewCycle, NewRR} =
+ case unfold(RemType, C) of
+ true -> {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
+ false -> {t_any(), C, [RemType]}
+ end,
+ {NewRep, RR} = t_solve_remote(Rep, ET, R, NewCycle),
+ RetRR = NewRR ++ RR,
+ RT1 =
+ case lists:member(RemType, RetRR) of
+ true -> t_limit(NewRep, ?REC_TYPE_LIMIT);
+ false -> NewRep
+ end,
+ {t_from_form({opaque, -1, Name, {Mod, Args, RT1}},
+ RemDict, TmpVarDict),
+ RetRR};
+ {type, _} ->
+ Msg = io_lib:format("Unknown remote type ~w\n", [Name]),
+ throw({error, Msg});
+ {opaque, _} ->
+ Msg = io_lib:format("Unknown remote opaque type ~w\n", [Name]),
+ throw({error, Msg});
+ error ->
+ Msg = io_lib:format("Unable to find remote type ~w:~w()\n",
+ [RemMod, Name]),
+ throw({error, Msg})
+ end;
+ false ->
+ self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
+ {t_any(), []}
end
end.
-list_solve_remote([], _R, _C) ->
+list_solve_remote([], _ET, _R, _C) ->
{[], []};
-list_solve_remote([Type|Types], R, C) ->
- {RT, RR1} = t_solve_remote(Type, R, C),
- {RL, RR2} = list_solve_remote(Types, R, C),
+list_solve_remote([Type|Types], ET, R, C) ->
+ {RT, RR1} = t_solve_remote(Type, ET, R, C),
+ {RL, RR2} = list_solve_remote(Types, ET, R, C),
{[RT|RL], RR1 ++ RR2}.
-list_solve_remote_type([], _R, _C) ->
+list_solve_remote_type([], _ET, _R, _C) ->
{[], []};
-list_solve_remote_type([Type|Types], R, C) ->
- {RT, RR1} = t_solve_remote_type(Type, R, C),
- {RL, RR2} = list_solve_remote_type(Types, R, C),
+list_solve_remote_type([Type|Types], ET, R, C) ->
+ {RT, RR1} = t_solve_remote_type(Type, ET, R, C),
+ {RL, RR2} = list_solve_remote_type(Types, ET, R, C),
{[RT|RL], RR1 ++ RR2}.
-opaques_solve_remote([], _R, _C) ->
+opaques_solve_remote([], _ET, _R, _C) ->
{[], []};
-opaques_solve_remote([#opaque{struct = Struct} = Remote|Tail], R, C) ->
- {RT, RR1} = t_solve_remote(Struct, R, C),
- {LOp, RR2} = opaques_solve_remote(Tail, R, C),
+opaques_solve_remote([#opaque{struct = Struct} = Remote|Tail], ET, R, C) ->
+ {RT, RR1} = t_solve_remote(Struct, ET, R, C),
+ {LOp, RR2} = opaques_solve_remote(Tail, ET, R, C),
{[Remote#opaque{struct = RT}|LOp], RR1 ++ RR2}.
-tuples_solve_remote([], _R, _C) ->
+tuples_solve_remote([], _ET, _R, _C) ->
{[], []};
-tuples_solve_remote([{Sz, Tuples}|Tail], R, C) ->
- {RL, RR1} = list_solve_remote(Tuples, R, C),
- {LSzTpls, RR2} = tuples_solve_remote(Tail, R, C),
+tuples_solve_remote([{Sz, Tuples}|Tail], ET, R, C) ->
+ {RL, RR1} = list_solve_remote(Tuples, ET, R, C),
+ {LSzTpls, RR2} = tuples_solve_remote(Tail, ET, R, C),
{[{Sz, RL}|LSzTpls], RR1 ++ RR2}.
%%-----------------------------------------------------------------------------
@@ -801,7 +813,7 @@ t_is_none_or_unit(?unit) -> true;
t_is_none_or_unit(_) -> false.
%%-----------------------------------------------------------------------------
-%% Atoms and the derived type bool
+%% Atoms and the derived type boolean
%%
-spec t_atom() -> erl_type().
@@ -1596,7 +1608,7 @@ t_set() ->
t_tid() ->
t_opaque(ets, tid, [], t_integer()).
--spec all_opaque_builtins() -> [erl_type()].
+-spec all_opaque_builtins() -> [erl_type(),...].
all_opaque_builtins() ->
[t_array(), t_dict(), t_digraph(), t_gb_set(),
@@ -2523,12 +2535,14 @@ t_subst(T, _Dict, _Fun) ->
%% Unification
%%
--spec t_unify(erl_type(), erl_type()) -> {erl_type(), [{_, erl_type()}]}.
+-type t_unify_ret() :: {erl_type(), [{_, erl_type()}]}.
+
+-spec t_unify(erl_type(), erl_type()) -> t_unify_ret().
t_unify(T1, T2) ->
t_unify(T1, T2, []).
--spec t_unify(erl_type(), erl_type(), [erl_type()]) -> {erl_type(), [{_, erl_type()}]}.
+-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),
@@ -2541,7 +2555,7 @@ t_unify(?var(Id1) = T, ?var(Id2), Dict, Opaques) ->
error ->
case dict:find(Id2, Dict) of
error -> {T, dict:store(Id2, T, Dict)};
- {ok, Type} -> {Type, t_unify(T, Type, Dict, Opaques)}
+ {ok, Type} -> t_unify(T, Type, Dict, Opaques)
end;
{ok, Type1} ->
case dict:find(Id2, Dict) of
@@ -3298,28 +3312,44 @@ record_to_string(Tag, [_|Fields], FieldNames, RecDict) ->
FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []),
"#" ++ atom_to_list(Tag) ++ "{" ++ sequence(FieldStrings, [], ",") ++ "}".
-record_fields_to_string([Field|Left1], [{FieldName, DeclaredType}|Left2],
- RecDict, Acc) ->
- PrintType =
- case t_is_equal(Field, DeclaredType) of
- true -> false;
+record_fields_to_string([F|Fs], [{FName, _DefType}|FDefs], RecDict, Acc) ->
+ NewAcc =
+ case t_is_any(F) orelse t_is_atom('undefined', F) of
+ true -> Acc;
false ->
- case t_is_any(DeclaredType) andalso t_is_atom(undefined, Field) of
- true -> false;
- false ->
- TmpType = t_subtract(DeclaredType, t_atom(undefined)),
- not t_is_equal(Field, TmpType)
- end
+ StrFV = atom_to_list(FName) ++ "::" ++ t_to_string(F, RecDict),
+ %% ActualDefType = t_subtract(DefType, t_atom('undefined')),
+ %% Str = case t_is_any(ActualDefType) of
+ %% true -> StrFV;
+ %% false -> StrFV ++ "::" ++ t_to_string(ActualDefType, RecDict)
+ %% end,
+ [StrFV|Acc]
end,
- case PrintType of
- false -> record_fields_to_string(Left1, Left2, RecDict, Acc);
- true ->
- String = atom_to_list(FieldName) ++ "::" ++ t_to_string(Field, RecDict),
- record_fields_to_string(Left1, Left2, RecDict, [String|Acc])
- end;
+ record_fields_to_string(Fs, FDefs, RecDict, NewAcc);
record_fields_to_string([], [], _RecDict, Acc) ->
lists:reverse(Acc).
+-spec record_field_diffs_to_string(erl_type(), dict()) -> string().
+
+record_field_diffs_to_string(?tuple([_|Fs], Arity, Tag), RecDict) ->
+ [TagAtom] = t_atom_vals(Tag),
+ {ok, FieldNames} = lookup_record(TagAtom, Arity-1, RecDict),
+ %% io:format("RecCElems = ~p\nRecTypes = ~p\n", [Fs, FieldNames]),
+ FieldDiffs = field_diffs(Fs, FieldNames, RecDict, []),
+ sequence(FieldDiffs, [], " and ").
+
+field_diffs([F|Fs], [{FName, DefType}|FDefs], RecDict, Acc) ->
+ NewAcc =
+ case t_is_subtype(F, DefType) of
+ true -> Acc;
+ false ->
+ Str = atom_to_list(FName) ++ "::" ++ t_to_string(DefType, RecDict),
+ [Str|Acc]
+ end,
+ field_diffs(Fs, FDefs, RecDict, NewAcc);
+field_diffs([], [], _, Acc) ->
+ lists:reverse(Acc).
+
comma_sequence(Types, RecDict) ->
List = [case T =:= ?any of
true -> "_";
@@ -3338,8 +3368,8 @@ sequence([], [], _Delimiter) ->
[];
sequence([T], Acc, _Delimiter) ->
lists:flatten(lists:reverse([T|Acc]));
-sequence([T|Left], Acc, Delimiter) ->
- sequence(Left, [T ++ Delimiter|Acc], Delimiter).
+sequence([T|Ts], Acc, Delimiter) ->
+ sequence(Ts, [T ++ Delimiter|Acc], Delimiter).
%%=============================================================================
%%
@@ -3360,174 +3390,248 @@ t_from_form(Form, RecDict) ->
-spec t_from_form(parse_form(), dict(), dict()) -> erl_type().
t_from_form(Form, RecDict, VarDict) ->
- {T, _R} = t_from_form(Form, [], RecDict, VarDict),
+ {T, _R} = t_from_form(Form, [], false, RecDict, VarDict),
T.
-type type_names() :: [{'type' | 'opaque' | 'record', atom()}].
--spec t_from_form(parse_form(), type_names(), dict(), dict()) ->
+-spec t_from_form(parse_form(), type_names(), boolean(), dict(), dict()) ->
{erl_type(), type_names()}.
-t_from_form({var, _L, '_'}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({var, _L, '_'}, _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{t_any(), []};
-t_from_form({var, _L, Name}, _TypeNames, _RecDict, VarDict) ->
+t_from_form({var, _L, Name}, _TypeNames, _InOpaque, _RecDict, VarDict) ->
case dict:find(Name, VarDict) of
error -> {t_var(Name), []};
{ok, Val} -> {Val, []}
end;
-t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, RecDict, VarDict) ->
- t_from_form(Type, TypeNames, RecDict, VarDict);
-t_from_form({paren_type, _L, [Type]}, TypeNames, RecDict, VarDict) ->
- t_from_form(Type, TypeNames, RecDict, VarDict);
+t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict);
+t_from_form({paren_type, _L, [Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict);
t_from_form({remote_type, _L, [{atom, _, Module}, {atom, _, Type}, Args]},
- TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R} = list_from_form(Args, TypeNames, InOpaque, RecDict, VarDict),
{t_remote(Module, Type, L), R};
-t_from_form({atom, _L, Atom}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({atom, _L, Atom}, _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{t_atom(Atom), []};
-t_from_form({integer, _L, Int}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({integer, _L, Int}, _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{t_integer(Int), []};
-t_from_form({type, _L, any, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({op, _L, _Op, _Arg} = Op, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
+ case erl_eval:partial_eval(Op) of
+ {integer, _, Val} ->
+ {t_integer(Val), []};
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])})
+ end;
+t_from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _TypeNames, _InOpaque,
+ _RecDict, _VarDict) ->
+ case erl_eval:partial_eval(Op) of
+ {integer, _, Val} ->
+ {t_integer(Val), []};
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])})
+ end;
+t_from_form({type, _L, any, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_any(), []};
-t_from_form({type, _L, arity, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, arity, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_arity(), []};
-t_from_form({type, _L, array, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, array, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_array(), []};
-t_from_form({type, _L, atom, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, atom, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_atom(), []};
-t_from_form({type, _L, binary, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, binary, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_binary(), []};
-t_from_form({type, _L, binary, [{integer, _, Base}, {integer, _, Unit}]},
- _TypeNames, _RecDict, _VarDict) ->
- {t_bitstr(Unit, Base), []};
-t_from_form({type, _L, bitstring, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, binary, [Base, Unit]} = Type,
+ _TypeNames, _InOpaque, _RecDict, _VarDict) ->
+ case {erl_eval:partial_eval(Base), erl_eval:partial_eval(Unit)} of
+ {{integer, _, BaseVal},
+ {integer, _, UnitVal}}
+ when BaseVal >= 0, UnitVal >= 0 ->
+ {t_bitstr(UnitVal, BaseVal), []};
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])})
+ end;
+t_from_form({type, _L, bitstring, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_bitstr(), []};
-t_from_form({type, _L, bool, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, bool, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_boolean(), []}; % XXX: Temporarily
-t_from_form({type, _L, boolean, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, boolean, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_boolean(), []};
-t_from_form({type, _L, byte, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, byte, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_byte(), []};
-t_from_form({type, _L, char, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, char, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_char(), []};
-t_from_form({type, _L, dict, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, dict, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_dict(), []};
-t_from_form({type, _L, digraph, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, digraph, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_digraph(), []};
-t_from_form({type, _L, float, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, float, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_float(), []};
-t_from_form({type, _L, function, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, function, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_fun(), []};
-t_from_form({type, _L, 'fun', []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, 'fun', []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_fun(), []};
t_from_form({type, _L, 'fun', [{type, _, any, []}, Range]}, TypeNames,
- RecDict, VarDict) ->
- {T, R} = t_from_form(Range, TypeNames, RecDict, VarDict),
+ InOpaque, RecDict, VarDict) ->
+ {T, R} = t_from_form(Range, TypeNames, InOpaque, RecDict, VarDict),
{t_fun(T), R};
t_from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]},
- TypeNames, RecDict, VarDict) ->
- {L, R1} = list_from_form(Domain, TypeNames, RecDict, VarDict),
- {T, R2} = t_from_form(Range, TypeNames, RecDict, VarDict),
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R1} = list_from_form(Domain, TypeNames, InOpaque, RecDict, VarDict),
+ {T, R2} = t_from_form(Range, TypeNames, InOpaque, RecDict, VarDict),
{t_fun(L, T), R1 ++ R2};
-t_from_form({type, _L, gb_set, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, gb_set, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_gb_set(), []};
-t_from_form({type, _L, gb_tree, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, gb_tree, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_gb_tree(), []};
-t_from_form({type, _L, identifier, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, identifier, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_identifier(), []};
-t_from_form({type, _L, integer, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, integer, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_integer(), []};
-t_from_form({type, _L, iodata, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, iodata, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_iodata(), []};
-t_from_form({type, _L, iolist, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, iolist, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_iolist(), []};
-t_from_form({type, _L, list, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, list, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_list(), []};
-t_from_form({type, _L, list, [Type]}, TypeNames, RecDict, VarDict) ->
- {T, R} = t_from_form(Type, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, list, [Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {T, R} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
{t_list(T), R};
-t_from_form({type, _L, mfa, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, mfa, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_mfa(), []};
-t_from_form({type, _L, module, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, module, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_module(), []};
-t_from_form({type, _L, nil, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, nil, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_nil(), []};
-t_from_form({type, _L, neg_integer, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, neg_integer, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_neg_integer(), []};
-t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_non_neg_integer(), []};
-t_from_form({type, _L, no_return, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, no_return, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_unit(), []};
-t_from_form({type, _L, node, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, node, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_node(), []};
-t_from_form({type, _L, none, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, none, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_none(), []};
-t_from_form({type, _L, nonempty_list, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, nonempty_list, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_nonempty_list(), []};
-t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, RecDict, VarDict) ->
- {T, R} = t_from_form(Type, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {T, R} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
{t_nonempty_list(T), R};
t_from_form({type, _L, nonempty_improper_list, [Cont, Term]}, TypeNames,
- RecDict, VarDict) ->
- {T1, R1} = t_from_form(Cont, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Term, TypeNames, RecDict, VarDict),
+ InOpaque, RecDict, VarDict) ->
+ {T1, R1} = t_from_form(Cont, TypeNames, InOpaque, RecDict, VarDict),
+ {T2, R2} = t_from_form(Term, TypeNames, InOpaque, RecDict, VarDict),
{t_cons(T1, T2), R1 ++ R2};
t_from_form({type, _L, nonempty_maybe_improper_list, []}, _TypeNames,
- _RecDict, _VarDict) ->
+ _InOpaque, _RecDict, _VarDict) ->
{t_cons(?any, ?any), []};
-t_from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]}, TypeNames,
- RecDict, VarDict) ->
- {T1, R1} = t_from_form(Cont, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Term, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]},
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {T1, R1} = t_from_form(Cont, TypeNames, InOpaque, RecDict, VarDict),
+ {T2, R2} = t_from_form(Term, TypeNames, InOpaque, RecDict, VarDict),
{t_cons(T1, T2), R1 ++ R2};
-t_from_form({type, _L, nonempty_string, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, nonempty_string, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_nonempty_string(), []};
-t_from_form({type, _L, number, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, number, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_number(), []};
-t_from_form({type, _L, pid, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, pid, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_pid(), []};
-t_from_form({type, _L, port, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, port, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_port(), []};
-t_from_form({type, _L, pos_integer, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_pos_integer(), []};
-t_from_form({type, _L, maybe_improper_list, []}, _TypeNames, _RecDict,
+t_from_form({type, _L, pos_integer, []}, _TypeNames, _InOpaque, _RecDict,
_VarDict) ->
+ {t_pos_integer(), []};
+t_from_form({type, _L, maybe_improper_list, []}, _TypeNames, _InOpaque,
+ _RecDict, _VarDict) ->
{t_maybe_improper_list(), []};
-t_from_form({type, _L, maybe_improper_list, [Content, Termination]}, TypeNames,
- RecDict, VarDict) ->
- {T1, R1} = t_from_form(Content, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Termination, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, maybe_improper_list, [Content, Termination]},
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {T1, R1} = t_from_form(Content, TypeNames, InOpaque, RecDict, VarDict),
+ {T2, R2} = t_from_form(Termination, TypeNames, InOpaque, RecDict, VarDict),
{t_maybe_improper_list(T1, T2), R1 ++ R2};
-t_from_form({type, _L, product, Elements}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Elements, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, product, Elements}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {L, R} = list_from_form(Elements, TypeNames, InOpaque, RecDict, VarDict),
{t_product(L), R};
-t_from_form({type, _L, queue, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, queue, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_queue(), []};
-t_from_form({type, _L, range, [{integer, _, From}, {integer, _, To}]},
- _TypeNames, _RecDict, _VarDict) ->
- {t_from_range(From, To), []};
-t_from_form({type, _L, record, [Name|Fields]}, TypeNames, RecDict, VarDict) ->
- record_from_form(Name, Fields, TypeNames, RecDict, VarDict);
-t_from_form({type, _L, reference, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, range, [From, To]} = Type,
+ _TypeNames, _InOpaque, _RecDict, _VarDict) ->
+ case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of
+ {{integer, _, FromVal}, {integer, _, ToVal}} ->
+ {t_from_range(FromVal, ToVal), []};
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])})
+ end;
+t_from_form({type, _L, record, [Name|Fields]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ record_from_form(Name, Fields, TypeNames, InOpaque, RecDict, VarDict);
+t_from_form({type, _L, reference, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_reference(), []};
-t_from_form({type, _L, set, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, set, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_set(), []};
-t_from_form({type, _L, string, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, string, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_string(), []};
-t_from_form({type, _L, term, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, term, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_any(), []};
-t_from_form({type, _L, tid, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, tid, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_tid(), []};
-t_from_form({type, _L, timeout, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, timeout, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_timeout(), []};
-t_from_form({type, _L, tuple, any}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, tuple, any}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_tuple(), []};
-t_from_form({type, _L, tuple, Args}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, tuple, Args}, TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R} = list_from_form(Args, TypeNames, InOpaque, RecDict, VarDict),
{t_tuple(L), R};
-t_from_form({type, _L, union, Args}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, union, Args}, TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R} = list_from_form(Args, TypeNames, InOpaque, RecDict, VarDict),
{t_sup(L), R};
-t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
+t_from_form({type, _L, Name, Args}, TypeNames, InOpaque, RecDict, VarDict) ->
case lookup_type(Name, RecDict) of
{type, {_Module, Type, ArgNames}} when length(Args) =:= length(ArgNames) ->
case unfold({type, Name}, TypeNames) of
@@ -3535,13 +3639,14 @@ t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
List = lists:zipwith(
fun(ArgName, ArgType) ->
{Ttemp, _R} = t_from_form(ArgType, TypeNames,
- RecDict, VarDict),
+ InOpaque, RecDict,
+ VarDict),
{ArgName, Ttemp}
end,
ArgNames, Args),
TmpVarDict = dict:from_list(List),
- {T, R} = t_from_form(Type, [{type, Name}|TypeNames], RecDict,
- TmpVarDict),
+ {T, R} = t_from_form(Type, [{type, Name}|TypeNames], InOpaque,
+ RecDict, TmpVarDict),
case lists:member({type, Name}, R) of
true -> {t_limit(T, ?REC_TYPE_LIMIT), R};
false -> {T, R}
@@ -3554,22 +3659,28 @@ t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
true ->
List = lists:zipwith(
fun(ArgName, ArgType) ->
- {Ttemp, _R} = t_from_form(ArgType, TypeNames,
- RecDict, VarDict),
+ {Ttemp, _R} = t_from_form(ArgType, TypeNames,
+ InOpaque, RecDict,
+ VarDict),
{ArgName, Ttemp}
end,
ArgNames, Args),
TmpVarDict = dict:from_list(List),
- {T, R} = t_from_form(Type, [{opaque, Name}|TypeNames], RecDict,
- TmpVarDict),
+ {T, R} = t_from_form(Type, [{opaque, Name}|TypeNames], true,
+ RecDict, TmpVarDict),
case lists:member({opaque, Name}, R) of
true -> {t_limit(T, ?REC_TYPE_LIMIT), R};
false -> {T, R}
end;
false -> {t_any(), [{opaque, Name}]}
end,
- Tret = t_from_form({opaque, -1, Name, {Module, Args, Rep}},
- RecDict, VarDict),
+ Tret =
+ case InOpaque of
+ true -> Rep;
+ false ->
+ t_from_form({opaque, -1, Name, {Module, Args, Rep}},
+ RecDict, VarDict)
+ end,
{Tret, Rret};
{type, _} ->
throw({error, io_lib:format("Unknown type ~w\n", [Name])});
@@ -3578,14 +3689,15 @@ t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
error ->
throw({error, io_lib:format("Unable to find type ~w\n", [Name])})
end;
-t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, _RecDict,
- _VarDict) ->
+t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, _InOpaque,
+ _RecDict, _VarDict) ->
case Args of
[] -> {t_opaque(Mod, Name, Args, Rep), []};
_ -> throw({error, "Polymorphic opaque types not supported yet"})
end.
-record_from_form({atom, _, Name}, ModFields, TypeNames, RecDict, VarDict) ->
+record_from_form({atom, _, Name}, ModFields, TypeNames, InOpaque, RecDict,
+ VarDict) ->
case unfold({record, Name}, TypeNames) of
true ->
case lookup_record(Name, RecDict) of
@@ -3596,11 +3708,12 @@ record_from_form({atom, _, Name}, ModFields, TypeNames, RecDict, VarDict) ->
{DeclFields1, R1} =
case lists:all(fun(Elem) -> Elem end, AreTyped) of
true -> {DeclFields, []};
- false -> fields_from_form(DeclFields, TypeNames1,
+ false -> fields_from_form(DeclFields, TypeNames1, InOpaque,
RecDict, dict:new())
end,
{GetModRec, R2} = get_mod_record(ModFields, DeclFields1,
- TypeNames1, RecDict, VarDict),
+ TypeNames1, InOpaque,
+ RecDict, VarDict),
case GetModRec of
{error, FieldName} ->
throw({error, io_lib:format("Illegal declaration of ~w#{~w}\n",
@@ -3617,11 +3730,13 @@ record_from_form({atom, _, Name}, ModFields, TypeNames, RecDict, VarDict) ->
false -> {t_any(), []}
end.
-get_mod_record([], DeclFields, _TypeNames, _RecDict, _VarDict) ->
+get_mod_record([], DeclFields, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{{ok, DeclFields}, []};
-get_mod_record(ModFields, DeclFields, TypeNames, RecDict, VarDict) ->
+get_mod_record(ModFields, DeclFields, TypeNames, InOpaque, RecDict,
+ VarDict) ->
DeclFieldsDict = orddict:from_list(DeclFields),
- {ModFieldsDict, R} = build_field_dict(ModFields, TypeNames,
+ {ModFieldsDict, R} = build_field_dict(ModFields, TypeNames, InOpaque,
RecDict, VarDict),
case get_mod_record(DeclFieldsDict, ModFieldsDict, []) of
{error, _FieldName} = Error -> {Error, R};
@@ -3631,21 +3746,23 @@ get_mod_record(ModFields, DeclFields, TypeNames, RecDict, VarDict) ->
R}
end.
-build_field_dict(FieldTypes, TypeNames, RecDict, VarDict) ->
- build_field_dict(FieldTypes, TypeNames, RecDict, VarDict, []).
+build_field_dict(FieldTypes, TypeNames, InOpaque, RecDict, VarDict) ->
+ build_field_dict(FieldTypes, TypeNames, InOpaque, RecDict, VarDict, []).
build_field_dict([{type, _, field_type, [{atom, _, Name}, Type]}|Left],
- TypeNames, RecDict, VarDict, Acc) ->
- {T, R1} = t_from_form(Type, TypeNames, RecDict, VarDict),
+ TypeNames, InOpaque, RecDict, VarDict, Acc) ->
+ {T, R1} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
NewAcc = [{Name, T}|Acc],
- {D, R2} = build_field_dict(Left, TypeNames, RecDict, VarDict, NewAcc),
+ {D, R2} = build_field_dict(Left, TypeNames, InOpaque, RecDict, VarDict,
+ NewAcc),
{D, R1 ++ R2};
-build_field_dict([], _TypeNames, _RecDict, _VarDict, Acc) ->
+build_field_dict([], _TypeNames, _InOpaque, _RecDict, _VarDict, Acc) ->
{orddict:from_list(Acc), []}.
get_mod_record([{FieldName, DeclType}|Left1],
[{FieldName, ModType}|Left2], Acc) ->
- case t_is_var(ModType) orelse t_is_subtype(ModType, DeclType) of
+ case t_is_var(ModType) orelse t_is_remote(ModType) orelse
+ t_is_subtype(ModType, DeclType) of
false -> {error, FieldName};
true -> get_mod_record(Left1, Left2, [{FieldName, ModType}|Acc])
end;
@@ -3658,18 +3775,19 @@ get_mod_record(DeclFields, [], Acc) ->
get_mod_record(_, [{FieldName2, _ModType}|_], _Acc) ->
{error, FieldName2}.
-fields_from_form([], _TypeNames, _RecDict, _VarDict) ->
+fields_from_form([], _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{[], []};
-fields_from_form([{Name, Type}|Tail], TypeNames, RecDict, VarDict) ->
- {T, R1} = t_from_form(Type, TypeNames, RecDict, VarDict),
- {F, R2} = fields_from_form(Tail, TypeNames, RecDict, VarDict),
+fields_from_form([{Name, Type}|Tail], TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {T, R1} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
+ {F, R2} = fields_from_form(Tail, TypeNames, InOpaque, RecDict, VarDict),
{[{Name, T}|F], R1 ++ R2}.
-list_from_form([], _TypeNames, _RecDict, _VarDict) ->
+list_from_form([], _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{[], []};
-list_from_form([H|Tail], TypeNames, RecDict, VarDict) ->
- {T, R1} = t_from_form(H, TypeNames, RecDict, VarDict),
- {L, R2} = list_from_form(Tail, TypeNames, RecDict, VarDict),
+list_from_form([H|Tail], TypeNames, InOpaque, RecDict, VarDict) ->
+ {T, R1} = t_from_form(H, TypeNames, InOpaque, RecDict, VarDict),
+ {L, R2} = list_from_form(Tail, TypeNames, InOpaque, RecDict, VarDict),
{[T|L], R1 ++ R2}.
-spec t_form_to_string(parse_form()) -> string().
@@ -3679,6 +3797,16 @@ t_form_to_string({var, _L, Name}) -> atom_to_list(Name);
t_form_to_string({atom, _L, Atom}) ->
io_lib:write_string(atom_to_list(Atom), $'); % To quote or not to quote... '
t_form_to_string({integer, _L, Int}) -> integer_to_list(Int);
+t_form_to_string({op, _L, _Op, _Arg} = Op) ->
+ case erl_eval:partial_eval(Op) of
+ {integer, _, _} = Int -> t_form_to_string(Int);
+ _ -> io_lib:format("Bad formed type ~w",[Op])
+ end;
+t_form_to_string({op, _L, _Op, _Arg1, _Arg2} = Op) ->
+ case erl_eval:partial_eval(Op) of
+ {integer, _, _} = Int -> t_form_to_string(Int);
+ _ -> io_lib:format("Bad formed type ~w",[Op])
+ end;
t_form_to_string({ann_type, _L, [Var, Type]}) ->
t_form_to_string(Var) ++ "::" ++ t_form_to_string(Type);
t_form_to_string({paren_type, _L, [Type]}) ->
@@ -3705,8 +3833,12 @@ t_form_to_string({type, _L, nonempty_list, [Type]}) ->
t_form_to_string({type, _L, nonempty_string, []}) -> "nonempty_string()";
t_form_to_string({type, _L, product, Elements}) ->
"<" ++ sequence(t_form_to_string_list(Elements), ",") ++ ">";
-t_form_to_string({type, _L, range, [{integer, _, From}, {integer, _, To}]}) ->
- io_lib:format("~w..~w", [From, To]);
+t_form_to_string({type, _L, range, [From, To]} = Type) ->
+ case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of
+ {{integer, _, FromVal}, {integer, _, ToVal}} ->
+ io_lib:format("~w..~w", [FromVal, ToVal]);
+ _ -> io_lib:format("Bad formed type ~w",[Type])
+ end;
t_form_to_string({type, _L, record, [{atom, _, Name}]}) ->
io_lib:format("#~w{}", [Name]);
t_form_to_string({type, _L, record, [{atom, _, Name}|Fields]}) ->
@@ -3725,13 +3857,17 @@ t_form_to_string({type, _L, Name, []} = T) ->
try t_to_string(t_from_form(T))
catch throw:{error, _} -> atom_to_list(Name) ++ "()"
end;
-t_form_to_string({type, _L, binary, [{integer, _, X}, {integer, _, Y}]}) ->
- case Y of
- 0 ->
- case X of
- 0 -> "<<>>";
- _ -> io_lib:format("<<_:~w>>", [X])
- end
+t_form_to_string({type, _L, binary, [X,Y]} = Type) ->
+ case {erl_eval:partial_eval(X), erl_eval:partial_eval(Y)} of
+ {{integer, _, XVal}, {integer, _, YVal}} ->
+ case YVal of
+ 0 ->
+ case XVal of
+ 0 -> "<<>>";
+ _ -> io_lib:format("<<_:~w>>", [XVal])
+ end
+ end;
+ _ -> io_lib:format("Bad formed type ~w",[Type])
end;
t_form_to_string({type, _L, Name, List}) ->
io_lib:format("~w(~s)", [Name, sequence(t_form_to_string_list(List), ",")]).
@@ -3763,6 +3899,8 @@ any_none_or_unit([?unit|_]) -> true;
any_none_or_unit([_|Left]) -> any_none_or_unit(Left);
any_none_or_unit([]) -> false.
+-spec is_erl_type(any()) -> boolean().
+
is_erl_type(?any) -> true;
is_erl_type(?none) -> true;
is_erl_type(?unit) -> true;
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 2c78558190..cf30db0482 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -30,6 +30,91 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.7.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The HiPE compiler could crash when compiling certain
+ modules (the bug has been latent, and been exposed by new
+ optimizations introduced in the BEAM compiler in R14A).
+ (Thanks to Mikael Pettersson.)</p>
+ <p>
+ Own Id: OTP-8800</p>
+ </item>
+ <item>
+ <p>
+ hipe:load/1 was broken. (Thanks to Paul Guyot.)</p>
+ <p>
+ Own Id: OTP-8802</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.7.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p><c>receive</c> statements that can only read out a
+ newly created reference are now specially optimized so
+ that it will execute in constant time regardless of the
+ number of messages in the receive queue for the process.
+ That optimization will benefit calls to
+ <c>gen_server:call()</c>. (See <c>gen:do_call/4</c> for
+ an example of a receive statement that will be
+ optimized.)</p>
+ <p>
+ Own Id: OTP-8623</p>
+ </item>
+ <item>
+ <p>
+ Various changes to dialyzer-related files for R14.</p>
+ <p>
+ - Dialyzer properly supports the new attribute
+ -export_type and checks that remote types only refer to
+ exported types. A warning is produced if some
+ files/applications refer to types defined in modules
+ which are neither in the PLT nor in the analyzed
+ applications.</p>
+ <p>
+ - Support for detecting data races involving whereis/1
+ and unregister/1.</p>
+ <p>
+ - More precise identification of the reason(s) why a
+ record construction violates the types declared for its
+ fields.</p>
+ <p>
+ - Fixed bug in the handling of the 'or' guard.</p>
+ <p>
+ - Better handling of the erlang:element/2 BIF.</p>
+ <p>
+ - Complete handling of Erlang BIFs.</p>
+ <p>
+ Own Id: OTP-8699</p>
+ </item>
+ <item>
+ <p><c>eprof</c> has been reimplemented with support in
+ the Erlang virtual machine and is now both faster (i.e.
+ slows down the code being measured less) and scales much
+ better. In measurements we saw speed-ups compared to the
+ old eprof ranging from 6 times (for sequential code that
+ only uses one scheduler/core) up to 84 times (for
+ parallel code that uses 8 cores).</p>
+ <p>Note: The API for the <c>eprof</c> has been cleaned up
+ and extended. See the documentation.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8706</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.7.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/hipe/flow/hipe_dominators.erl b/lib/hipe/flow/hipe_dominators.erl
index 3bfa6d43c4..17357461a5 100644
--- a/lib/hipe/flow/hipe_dominators.erl
+++ b/lib/hipe/flow/hipe_dominators.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2010. 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%
%%
%%------------------------------------------------------------------------
@@ -37,6 +37,8 @@
domFrontier_create/2,
domFrontier_get/2]).
+-export_type([domTree/0]).
+
-include("cfg.hrl").
%%========================================================================
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 3923e98673..1f8be4040e 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2010. 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%
%%
%%=======================================================================
@@ -22,8 +22,6 @@
%% Author : Kostis Sagonas
%% Description : Translates symbolic BEAM code to Icode
%%=======================================================================
-%% $Id$
-%%=======================================================================
%% @doc
%% This file translates symbolic BEAM code to Icode which is HiPE's
%% intermediate code representation. Either the code of an entire
@@ -431,6 +429,11 @@ trans_fun([{wait_timeout,{_,Lbl},Reg}|Instructions], Env) ->
SuspTmout = hipe_icode:mk_if(suspend_msg_timeout,[],
map_label(Lbl),hipe_icode:label_name(DoneLbl)),
Movs ++ [SetTmout, SuspTmout, DoneLbl | trans_fun(Instructions,Env1)];
+%%--- recv_mark/1 & recv_set/1 --- XXX: Handle better??
+trans_fun([{recv_mark,{f,_}}|Instructions], Env) ->
+ trans_fun(Instructions,Env);
+trans_fun([{recv_set,{f,_}}|Instructions], Env) ->
+ trans_fun(Instructions,Env);
%%--------------------------------------------------------------------
%%--- Translation of arithmetics {bif,ArithOp, ...} ---
%%--------------------------------------------------------------------
@@ -892,11 +895,6 @@ trans_fun([{bs_init_bits,{f,Lbl},Size,_Words,_LiveRegs,{field_flags,Flags0},X}|
end,
trans_bin_call({hipe_bs_primop,Name}, Lbl, Args, [Dst, Base, Offset],
Base, Offset, Env, Instructions);
-trans_fun([{bs_bits_to_bytes2, Bits, Bytes}|Instructions], Env) ->
- Src = trans_arg(Bits),
- Dst = mk_var(Bytes),
- [hipe_icode:mk_primop([Dst], 'bsl', [Src, hipe_icode:mk_const(3)])|
- trans_fun(Instructions,Env)];
trans_fun([{bs_add, {f,Lbl}, [Old,New,Unit], Res}|Instructions], Env) ->
Dst = mk_var(Res),
Temp = mk_var(new),
@@ -1126,13 +1124,6 @@ trans_fun([{gc_bif,Name,Fail,_Live,SrcRs,DstR}|Instructions], Env) ->
trans_fun([{bif,Name,Fail,SrcRs,DstR}|Instructions], Env)
end;
%%--------------------------------------------------------------------
-%% Instruction for constant pool added in February 2007 for R11B-4.
-%%--------------------------------------------------------------------
-trans_fun([{put_literal,{literal,Literal},DstR}|Instructions], Env) ->
- DstV = mk_var(DstR),
- Move = hipe_icode:mk_move(DstV, hipe_icode:mk_const(Literal)),
- [Move | trans_fun(Instructions, Env)];
-%%--------------------------------------------------------------------
%% New test instruction added in July 2007 for R12.
%%--------------------------------------------------------------------
%%--- is_bitstr ---
diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl
index a4614d7237..3e211bf385 100644
--- a/lib/hipe/icode/hipe_icode.erl
+++ b/lib/hipe/icode/hipe_icode.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2010. 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%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1578,27 +1578,19 @@ redirect_jmp(Jmp, ToOld, ToNew) ->
_ -> Jmp
end
end,
- simplify_branch(NewI).
-
-%%
-%% @doc Turns a branch into a goto if it has only one successor and it
-%% is safe to do so.
-%%
-
--spec simplify_branch(icode_instr()) -> icode_instr().
-
-simplify_branch(I) ->
- case ordsets:from_list(successors(I)) of
+ %% Turn a branch into a goto if it has only one successor and it is
+ %% safe to do so.
+ case ordsets:from_list(successors(NewI)) of
[Label] ->
Goto = mk_goto(Label),
- case I of
- #icode_type{} -> Goto;
+ case NewI of
#icode_if{} -> Goto;
#icode_switch_tuple_arity{} -> Goto;
#icode_switch_val{} -> Goto;
- _ -> I
+ #icode_type{} -> Goto;
+ _ -> NewI
end;
- _ -> I
+ _ -> NewI
end.
%%
diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl
index 787fb05415..3c8f7b5712 100644
--- a/lib/hipe/icode/hipe_icode_exceptions.erl
+++ b/lib/hipe/icode/hipe_icode_exceptions.erl
@@ -344,6 +344,16 @@ pop_catch(Cs) ->
pop_catch_1([[_|C] | Cs]) ->
[C | pop_catch_1(Cs)];
+pop_catch_1([[] | Cs]) ->
+ %% The elements in the list represent different possible incoming
+ %% stacks of catch handlers to this BB. Before the fixpoint has
+ %% been found these elements are underapproximations of the true
+ %% stacks, therefore it's possible for these elements to be too
+ %% short for the number of pops implied by the code in the BB.
+ %% We must not fail in that case, so we set pop([]) = [].
+ %% This fixes find_catches_crash.erl and compiler_tests in the
+ %% HiPE test suite.
+ [[] | pop_catch_1(Cs)];
pop_catch_1([]) ->
[].
diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl
index 28198467f7..3f9488d7c3 100644
--- a/lib/hipe/icode/hipe_icode_type.erl
+++ b/lib/hipe/icode/hipe_icode_type.erl
@@ -2,19 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%% Copyright Ericsson AB 2003-2010. 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%
%%
%%%--------------------------------------------------------------------
@@ -23,8 +23,6 @@
%%% Description : Propagate type information.
%%%
%%% Created : 25 Feb 2003 by Tobias Lindahl <[email protected]>
-%%%
-%%% $Id$
%%%--------------------------------------------------------------------
-module(hipe_icode_type).
@@ -78,7 +76,7 @@
%-define(server_debug, fun(X, Y) -> io:format("~p server: ~s ~p~n", [self(), X, Y]) end).
-define(server_debug, fun(_, _) -> ok end).
--import(erl_types, [min/2, max/2, number_min/1, number_max/1,
+-import(erl_types, [number_min/1, number_max/1,
t_any/0, t_atom/1, t_atom/0, t_atom_vals/1,
t_binary/0, t_bitstr/0, t_bitstr_base/1, t_bitstr_unit/1,
t_boolean/0, t_cons/0, t_constant/0,
@@ -494,10 +492,10 @@ integer_range_less_then_propagator(IntArg1, IntArg2) ->
Min2 = number_min(IntArg2),
Max2 = number_max(IntArg2),
%% is this the same as erl_types:t_subtract?? no ... ??
- TrueMax1 = min(Max1, erl_bif_types:infinity_add(Max2, -1)),
- TrueMin2 = max(erl_bif_types:infinity_add(Min1, 1), Min2),
- FalseMin1 = max(Min1, Min2),
- FalseMax2 = min(Max1, Max2),
+ TrueMax1 = erl_types:min(Max1, erl_bif_types:infinity_add(Max2, -1)),
+ TrueMin2 = erl_types:max(erl_bif_types:infinity_add(Min1, 1), Min2),
+ FalseMin1 = erl_types:max(Min1, Min2),
+ FalseMax2 = erl_types:min(Max1, Max2),
{t_from_range(Min1, TrueMax1),
t_from_range(TrueMin2, Max2),
t_from_range(FalseMin1, Max1),
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index ed722fecba..c80fb6a0a2 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -274,7 +274,7 @@ load(Mod, BeamFileName) when is_list(BeamFileName) ->
Architecture = erlang:system_info(hipe_architecture),
ChunkName = hipe_unified_loader:chunk_name(Architecture),
case beam_lib:chunks(BeamFileName, [ChunkName]) of
- {ok,{_,[{_,Bin}]}} when is_binary(Bin) -> do_load(Mod, Bin, Bin);
+ {ok,{_,[{_,Bin}]}} when is_binary(Bin) -> do_load(Mod, Bin, BeamFileName);
Error -> {error, Error}
end.
@@ -913,7 +913,7 @@ do_load(Mod, Bin, WholeModule) ->
%% In this case, the emulated code for the module must be loaded.
{module, Mod} = code:ensure_loaded(Mod),
code:load_native_partial(Mod, Bin);
- BinCode when is_binary(BinCode) ->
+ 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
diff --git a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
index ac555b933c..ce33af453a 100644
--- a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
@@ -389,23 +389,23 @@ decrement_each([N|Ns], OldLow, IG, Vis, K) ->
%% {Spilled_node, Low_degree_neighbors, New_interference_graph}
spill(IG, Vis, Spill, K, SpillLimit, Target) ->
- Ns = list_ig(IG),
- Costs = spill_costs(Ns, IG, Vis, Spill, SpillLimit, Target),
- ?report3("spill costs are ~p~n",[Costs]),
- ActualCosts = lists:sort(Costs),
- ?report3("actual costs are ~p~n",[ActualCosts]),
+ Ns = list_ig(IG),
+ Costs = spill_costs(Ns, IG, Vis, Spill, SpillLimit, Target),
+ ?report3("spill costs are ~p~n", [Costs]),
+ ActualCosts = lists:sort(Costs),
+ ?report3("actual costs are ~p~n", [ActualCosts]),
case ActualCosts of
- [] ->
- ?error_msg("There is no node to spill",[]),
+ [] ->
+ ?error_msg("There is no node to spill", []),
?EXIT('no node to spill');
[{_Cost,N}|_] ->
{Low, NewIG} = decrement_neighbors(N, [], IG, Vis, K),
- %?report("spilled node ~p at cost ~p (~p now ready)~n",[N,Cost,Low]),
+ %% ?report("spilled node ~p at cost ~p (~p now ready)~n", [N,Cost,Low]),
{N, Low, NewIG}
end.
spill_costs([], _IG, _Vis, _Spill, _SpillLimit, _Target) ->
- [];
+ [];
spill_costs([{N,Info}|Ns], IG, Vis, Spill, SpillLimit, Target) ->
case degree(Info) of
0 -> spill_costs(Ns,IG,Vis,Spill, SpillLimit, Target);
@@ -451,28 +451,28 @@ select_colors([{X,colorable}|Xs], IG, Cols, PhysRegs, K) ->
{Reg,NewCols} = select_color(X, IG, Cols, PhysRegs),
?report("~p~n",[Reg]),
[{X,{reg,Reg}} | select_colors(Xs, IG, NewCols, PhysRegs, K)];
-%select_colors([{X,{spill,M}}|Xs], IG, Cols, PhysRegs, K) ->
-% ?report('spilled: ~p~n',[X]),
-% %% Check if optimistic coloring could have found a color
-% case catch select_color(X,IG,Cols,K) of
-% {'EXIT',_} -> % no color possible
-% ?report('(no optimistic color)~n',[]),
-% [{X,{spill,M}}|select_colors(Xs, IG, Cols, PhysRegs, K)];
-% {Reg,NewCols} ->
-% ?report('(optimistic color: ~p)~n',[Reg]),
-% [{X,{reg,Reg}}|select_colors(Xs, IG, Cols, PhysRegs, K)]
-% end.
+%%select_colors([{X,{spill,M}}|Xs], IG, Cols, PhysRegs, K) ->
+%% ?report('spilled: ~p~n',[X]),
+%% %% Check if optimistic coloring could have found a color
+%% case catch select_color(X,IG,Cols,K) of
+%% {'EXIT',_} -> % no color possible
+%% ?report('(no optimistic color)~n',[]),
+%% [{X,{spill,M}}|select_colors(Xs, IG, Cols, PhysRegs, K)];
+%% {Reg,NewCols} ->
+%% ?report('(optimistic color: ~p)~n',[Reg]),
+%% [{X,{reg,Reg}}|select_colors(Xs, IG, Cols, PhysRegs, K)]
+%% end.
%% Old code / pessimistic coloring:
select_colors([{X,{spill,M}}|Xs], IG, Cols, PhysRegs, K) ->
?report("spilled: ~p~n",[X]),
%% Check if optimistic coloring could have found a color
-% case catch select_color(X,IG,Cols,K) of
-% {'EXIT',_} -> % no color possible
-% ?report('(no optimistic color)~n',[]);
-% {Reg,NewCols} ->
-% ?report('(optimistic color: ~p)~n',[Reg])
-% end,
+%% case catch select_color(X,IG,Cols,K) of
+%% {'EXIT',_} -> % no color possible
+%% ?report('(no optimistic color)~n',[]);
+%% {Reg,NewCols} ->
+%% ?report('(optimistic color: ~p)~n',[Reg])
+%% end,
[{X,{spill,M}} | select_colors(Xs, IG, Cols, PhysRegs, K)].
select_color(X, IG, Cols, PhysRegs) ->
diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl
index 560e0259f8..0361053676 100644
--- a/lib/hipe/rtl/hipe_rtl_primops.erl
+++ b/lib/hipe/rtl/hipe_rtl_primops.erl
@@ -701,9 +701,9 @@ gen_cons(Dst, [Arg1, Arg2]) ->
%% Increase refcount
%% fe->refc++;
%%
-%% Link to the process off_heap.funs list
-%% funp->next = p->off_heap.funs;
-%% p->off_heap.funs = funp;
+%% Link to the process off_heap list
+%% funp->next = p->off_heap.first;
+%% p->off_heap.first = funp;
%%
%% Tag the thing
%% return make_fun(funp);
@@ -729,9 +729,9 @@ gen_mkfun([Dst], {_Mod, _FunId, _Arity} = MFidA, MagicNr, Index, FreeVars) ->
%% fe->refc++;
SkeletonCode = gen_fun_thing_skeleton(HP, MFidA, NumFree, MagicNr, Index),
- %% Link to the process off_heap.funs list
- %% funp->next = p->off_heap.funs;
- %% p->off_heap.funs = funp;
+ %% Link to the process off_heap list
+ %% funp->next = p->off_heap.first;
+ %% p->off_heap.first = funp;
LinkCode = gen_link_closure(HP),
%% Tag the thing and increase the heap_pointer.
@@ -797,14 +797,14 @@ gen_link_closure(FUNP) ->
end.
gen_link_closure_private(FUNP) ->
- %% Link to the process off_heap.funs list
- %% funp->next = p->off_heap.funs;
- %% p->off_heap.funs = funp;
+ %% Link fun to the process off_heap list
+ %% funp->next = p->off_heap.first;
+ %% p->off_heap.first = funp;
FunsVar = hipe_rtl:mk_new_reg(),
- [load_p_field(FunsVar,?P_OFF_HEAP_FUNS),
+ [load_p_field(FunsVar,?P_OFF_HEAP_FIRST),
hipe_rtl:mk_store(FUNP, hipe_rtl:mk_imm(?EFT_NEXT), FunsVar),
- store_p_field(FUNP,?P_OFF_HEAP_FUNS)].
+ store_p_field(FUNP,?P_OFF_HEAP_FIRST)].
gen_link_closure_non_private(_FUNP) -> [].
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index dc44b803a1..c0b6dfad8a 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -849,9 +849,9 @@ create_refc_binary(Base, Size, Flags, Dst) ->
heap_arch_spec(HP) ->
Tmp1 = hipe_rtl:mk_new_reg(), % MSO state
- [hipe_rtl_arch:pcb_load(Tmp1, ?P_OFF_HEAP_MSO),
+ [hipe_rtl_arch:pcb_load(Tmp1, ?P_OFF_HEAP_FIRST),
set_field_from_pointer({proc_bin, next}, HP, Tmp1),
- hipe_rtl_arch:pcb_store(?P_OFF_HEAP_MSO, HP)].
+ hipe_rtl_arch:pcb_store(?P_OFF_HEAP_FIRST, HP)].
test_heap_binary(Binary, TrueLblName, FalseLblName) ->
Tmp1 = hipe_rtl:mk_new_reg_gcsafe(),
diff --git a/lib/hipe/util/hipe_digraph.erl b/lib/hipe/util/hipe_digraph.erl
index a62e913fe5..fcfaa64684 100644
--- a/lib/hipe/util/hipe_digraph.erl
+++ b/lib/hipe/util/hipe_digraph.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2010. 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%
%%
%%-----------------------------------------------------------------------
@@ -30,6 +30,8 @@
from_list/1, to_list/1, get_parents/2, get_children/2]).
-export([reverse_preorder_sccs/1]).
+-export_type([hdg/0]).
+
%%------------------------------------------------------------------------
-type ordset(T) :: [T]. % XXX: temporarily
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 129718a305..8e421ce9b2 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.7.5
+HIPE_VSN = 3.7.7
diff --git a/lib/hipe/x86/hipe_x86_spill_restore.erl b/lib/hipe/x86/hipe_x86_spill_restore.erl
index e60c446e17..cd927669fb 100644
--- a/lib/hipe/x86/hipe_x86_spill_restore.erl
+++ b/lib/hipe/x86/hipe_x86_spill_restore.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2010. 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%
%%
%% ====================================================================
@@ -71,9 +71,9 @@ firstPass(Defun) ->
case hipe_x86_cfg:reverse_postorder(CFG0) of
[Label1, Label2|_] ->
SaveTreeElement = saveTreeLookup(Label2, SaveTree),
- %% FilteredSaveTreeElement is the to be spilled temps around the function call.
- %% They are spilled just before move formals
- FilteredSaveTreeElement = [Temp || Temp <- SaveTreeElement, temp_is_pseudo(Temp)],
+ %% FilteredSaveTreeElement is the to be spilled temps around the
+ %% function call. They are spilled just before move formals.
+ FilteredSaveTreeElement = [T || T <- SaveTreeElement, temp_is_pseudo(T)],
Block = hipe_x86_cfg:bb(CFG1, Label1),
Code = hipe_bb:code(Block),
%% The following statements are tedious but work ok.
@@ -83,7 +83,7 @@ firstPass(Defun) ->
%% Another solution may be to introduce another block.
MoveCodes = lists:sublist(Code, length(Code)-1),
JumpCode = lists:last(Code),
- hipe_x86_cfg:bb_add(CFG1, Label1, hipe_bb:mk_bb(MoveCodes ++ [hipe_x86:mk_pseudo_spill(FilteredSaveTreeElement)] ++ [JumpCode]));
+ hipe_x86_cfg:bb_add(CFG1, Label1, hipe_bb:mk_bb(MoveCodes ++ [hipe_x86:mk_pseudo_spill(FilteredSaveTreeElement), JumpCode]));
_ ->
CFG1
end.
@@ -110,13 +110,12 @@ firstPassHelper([Label|Labels], Liveness, CFG, SaveTree) ->
NewBlock = hipe_bb:code_update(Block, NewCode),
NewCFG = hipe_x86_cfg:bb_add(CFG, Label, NewBlock),
SizeOfSet = setSize(NewIntersectedList),
-
%% if the Intersected Save List is not empty, insert it in the save tree.
if SizeOfSet =/= 0 ->
- UpdatedSaveTree = gb_trees:insert(Label,NewIntersectedList,SaveTree),
- firstPassHelper(Labels, Liveness, NewCFG,UpdatedSaveTree);
+ UpdatedSaveTree = gb_trees:insert(Label, NewIntersectedList, SaveTree),
+ firstPassHelper(Labels, Liveness, NewCFG, UpdatedSaveTree);
true ->
- firstPassHelper(Labels, Liveness, NewCFG,SaveTree)
+ firstPassHelper(Labels, Liveness, NewCFG, SaveTree)
end;
firstPassHelper([], _, CFG, SaveTree) ->
{CFG, SaveTree}.
@@ -125,17 +124,15 @@ firstPassHelper([], _, CFG, SaveTree) ->
firstPassDoBlock(Insts, LiveOut, IntersectedSaveList) ->
lists:foldr(fun firstPassDoInsn/2, {LiveOut,IntersectedSaveList,[]}, Insts).
-firstPassDoInsn(I, {LiveOut,IntersectedSaveList,PrevInsts} ) ->
+firstPassDoInsn(I, {LiveOut,IntersectedSaveList,PrevInsts}) ->
case I of
#pseudo_call{} ->
do_pseudo_call(I, {LiveOut,IntersectedSaveList,PrevInsts});
_ -> % other instructions
DefinedList = from_list( ?HIPE_X86_LIVENESS:defines(I)),
UsedList = from_list(?HIPE_X86_LIVENESS:uses(I)),
-
NewLiveOut = subtract(union(LiveOut, UsedList), DefinedList),
- NewIntersectedSaveList = subtract(IntersectedSaveList, DefinedList),
-
+ NewIntersectedSaveList = subtract(IntersectedSaveList, DefinedList),
{NewLiveOut, NewIntersectedSaveList, [I|PrevInsts]}
end.
@@ -162,7 +159,7 @@ saveTreeLookup(Label, SaveTree) ->
[]
end.
-%% Performs the second pass of the algoritm.
+%% Performs the second pass of the algorithm.
%% It basically eliminates the unnecessary spills and introduces restores.
%% Works top down
secondPass(CFG0) ->
@@ -306,7 +303,8 @@ addRestoreBlockToEdge(PseudoCall, ContLabel, CFG, TempArgsList) ->
NewCFG = hipe_x86_cfg:bb_add(CFG, NextLabel, NewBlock),
{NewCFG, NewPseudoCall}.
-%% used instead of hipe_x86_cfg:redirect_jmp since it does not handle pseudo_call calls.
+%% used instead of hipe_x86_cfg:redirect_jmp since it does not handle
+%% pseudo_call calls.
redirect_pseudo_call(I = #pseudo_call{contlab=ContLabel}, Old, New) ->
case Old =:= ContLabel of
true -> I#pseudo_call{contlab=New};
@@ -323,8 +321,8 @@ temp_is_pseudo(Temp) ->
%% Set operations where the module name is an easily changeable macro
%%---------------------------------------------------------------------
-union(Set1,Set2) ->
- ?SET_MODULE:union(Set1,Set2).
+union(Set1, Set2) ->
+ ?SET_MODULE:union(Set1, Set2).
setSize(Set) ->
?SET_MODULE:size(Set).