aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe')
-rw-r--r--lib/hipe/cerl/cerl_cconv.erl13
-rw-r--r--lib/hipe/cerl/cerl_hipeify.erl12
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl106
-rw-r--r--lib/hipe/cerl/erl_types.erl118
-rw-r--r--lib/hipe/doc/src/hipe_app.xml17
-rw-r--r--lib/hipe/doc/src/notes.xml77
-rw-r--r--lib/hipe/flow/cfg.hrl8
-rw-r--r--lib/hipe/icode/hipe_icode.erl42
-rw-r--r--lib/hipe/icode/hipe_icode.hrl3
-rw-r--r--lib/hipe/icode/hipe_icode_exceptions.erl20
-rw-r--r--lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl6
-rw-r--r--lib/hipe/main/hipe.erl5
-rw-r--r--lib/hipe/main/hipe.hrl.src5
-rw-r--r--lib/hipe/main/hipe_main.erl16
-rw-r--r--lib/hipe/rtl/Makefile2
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_construct.erl9
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_match.erl104
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl30
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_construct.erl16
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_match.erl108
-rw-r--r--lib/hipe/vsn.mk2
21 files changed, 410 insertions, 309 deletions
diff --git a/lib/hipe/cerl/cerl_cconv.erl b/lib/hipe/cerl/cerl_cconv.erl
index 0fc28be5f3..ac9d01ab0e 100644
--- a/lib/hipe/cerl/cerl_cconv.erl
+++ b/lib/hipe/cerl/cerl_cconv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -710,7 +710,7 @@ ren__new() ->
ren__add(Key, Value, Ren) ->
dict:store(Key, Value, Ren).
-ren__map(Key, Ren) ->
+ren__map(Key, Ren) ->
case dict:find(Key, Ren) of
{ok, Value} ->
Value;
@@ -722,11 +722,14 @@ ren__map(Key, Ren) ->
%% ---------------------------------------------------------------------
%% State
--record(state, {module :: module(), function :: {atom(), arity()},
- names, refs, defs = []}).
+-record(state, {module :: module(),
+ function :: {atom(), arity()} | 'undefined',
+ names = sets:new() :: sets:set(), %% XXX: refine
+ refs = dict:new() :: dict:dict(), %% XXX: refine
+ defs = []}).
s__new(Module) ->
- #state{module = Module, names = sets:new(), refs = dict:new()}.
+ #state{module = Module}.
s__add_function_name(Name, S) ->
S#state{names = sets:add_element(Name, S#state.names)}.
diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl
index 8691e80cac..6611abd204 100644
--- a/lib/hipe/cerl/cerl_hipeify.erl
+++ b/lib/hipe/cerl/cerl_hipeify.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -623,12 +623,12 @@ ren__map(Key, Ren) ->
%% ---------------------------------------------------------------------
%% State
-%% pmatch = 'true' | 'false' | 'no_duplicates' | 'duplicate_all'
+-type pmatch() :: 'true' | 'false' | 'no_duplicates' | 'duplicate_all'.
--record(state, {module::atom(),
- function::{atom(), 0..256},
- pmatch=true,
- revisit = false}).
+-record(state, {module :: module(),
+ function :: {atom(), arity()} | 'undefined',
+ pmatch = true :: pmatch(),
+ revisit = false :: boolean()}).
s__new(Module) ->
#state{module = Module}.
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 5387edfb47..622c235638 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -46,7 +46,6 @@
t_bitstr/0,
t_boolean/0,
t_byte/0,
- t_char/0,
t_cons/0,
t_cons/2,
t_cons_hd/1,
@@ -87,7 +86,6 @@
t_is_port/2,
t_is_maybe_improper_list/2,
t_is_reference/2,
- t_is_string/1,
t_is_subtype/2,
t_is_tuple/2,
t_list/0,
@@ -552,9 +550,6 @@ type(erlang, bit_size, 1, Xs, Opaques) ->
type(erlang, byte_size, 1, Xs, Opaques) ->
strict(erlang, byte_size, 1, Xs,
fun (_) -> t_non_neg_integer() end, Opaques);
-type(erlang, disconnect_node, 1, Xs, Opaques) ->
- strict(erlang, disconnect_node, 1, Xs,
- fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end, Opaques);
%% Guard bif, needs to be here.
%% Also much more expressive than anything you could write in a spec...
type(erlang, element, 2, Xs, Opaques) ->
@@ -583,16 +578,9 @@ type(erlang, element, 2, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, float, 1, Xs, Opaques) ->
strict(erlang, float, 1, Xs, fun (_) -> t_float() end, Opaques);
-type(erlang, fun_info, 1, Xs, Opaques) ->
- strict(erlang, fun_info, 1, Xs,
- fun (_) -> t_list(t_tuple([t_atom(), t_any()])) end, Opaques);
-type(erlang, get_cookie, 0, _, _Opaques) -> t_atom(); % | t_atom('nocookie')
%% Guard bif, needs to be here.
type(erlang, hd, 1, Xs, Opaques) ->
strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques);
-type(erlang, integer_to_list, 2, Xs, Opaques) ->
- strict(erlang, integer_to_list, 2, Xs,
- fun (_) -> t_string() end, Opaques);
type(erlang, info, 1, Xs, _) -> type(erlang, system_info, 1, Xs); % alias
%% All type tests are guard BIF's and may be implemented in ways that
%% cannot be expressed in a type spec, why they are kept in erl_bif_types.
@@ -768,6 +756,18 @@ type(erlang, length, 1, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, map_size, 1, Xs, Opaques) ->
strict(erlang, map_size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques);
+type(erlang, make_fun, 3, Xs, Opaques) ->
+ strict(erlang, make_fun, 3, Xs,
+ fun ([_, _, Arity]) ->
+ case t_number_vals(Arity, Opaques) of
+ [N] ->
+ case is_integer(N) andalso 0 =< N andalso N =< 255 of
+ true -> t_fun(N, t_any());
+ false -> t_none()
+ end;
+ _Other -> t_fun()
+ end
+ end, Opaques);
type(erlang, make_tuple, 2, Xs, Opaques) ->
strict(erlang, make_tuple, 2, Xs,
fun ([Int, _]) ->
@@ -784,8 +784,6 @@ type(erlang, make_tuple, 3, Xs, Opaques) ->
_Other -> t_tuple()
end
end, Opaques);
-type(erlang, memory, 0, _, _Opaques) ->
- t_list(t_tuple([t_atom(), t_non_neg_fixnum()]));
type(erlang, nif_error, 1, Xs, Opaques) ->
%% this BIF and the next one are stubs for NIFs and never return
strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end, Opaques);
@@ -801,8 +799,6 @@ type(erlang, round, 1, Xs, Opaques) ->
strict(erlang, round, 1, Xs, fun (_) -> t_integer() end, Opaques);
%% Guard bif, needs to be here.
type(erlang, self, 0, _, _Opaques) -> t_pid();
-type(erlang, set_cookie, 2, Xs, Opaques) ->
- strict(erlang, set_cookie, 2, Xs, fun (_) -> t_atom('true') end, Opaques);
type(erlang, setelement, 3, Xs, Opaques) ->
strict(erlang, setelement, 3, Xs,
fun ([X1, X2, X3]) ->
@@ -837,19 +833,7 @@ type(erlang, setelement, 3, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, size, 1, Xs, Opaques) ->
strict(erlang, size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques);
-type(erlang, spawn, 1, Xs, Opaques) ->
- strict(erlang, spawn, 1, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn, 2, Xs, Opaques) ->
- strict(erlang, spawn, 2, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn, 4, Xs, Opaques) ->
- strict(erlang, spawn, 4, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn_link, 1, Xs, _) -> type(erlang, spawn, 1, Xs); % same
-type(erlang, spawn_link, 2, Xs, _) -> type(erlang, spawn, 2, Xs); % same
-type(erlang, spawn_link, 4, Xs, _) -> type(erlang, spawn, 4, Xs); % same
type(erlang, subtract, 2, Xs, _Opaques) -> type(erlang, '--', 2, Xs); % alias
-type(erlang, suspend_process, 1, Xs, Opaques) ->
- strict(erlang, suspend_process, 1, Xs,
- fun (_) -> t_atom('true') end, Opaques);
type(erlang, system_info, 1, Xs, Opaques) ->
strict(erlang, system_info, 1, Xs,
fun ([Type]) ->
@@ -914,8 +898,7 @@ type(erlang, system_info, 1, Xs, Opaques) ->
t_list(t_pid());
['os_type'] ->
t_tuple([t_sup([t_atom('unix'),
- t_atom('win32'),
- t_atom('ose')]),
+ t_atom('win32')]),
t_atom()]);
['os_version'] ->
t_sup(t_tuple([t_non_neg_fixnum(),
@@ -1003,10 +986,6 @@ type(erlang, tuple_to_list, 1, Xs, Opaques) ->
end
end
end, Opaques);
-type(erlang, yield, 0, _, _Opaques) -> t_atom('true');
-%%-- ets ----------------------------------------------------------------------
-type(ets, rename, 2, Xs, Opaques) ->
- strict(ets, rename, 2, Xs, fun ([_, Name]) -> Name end, Opaques);
%%-- hipe_bifs ----------------------------------------------------------------
type(hipe_bifs, add_ref, 2, Xs, Opaques) ->
strict(hipe_bifs, add_ref, 2, Xs, fun (_) -> t_nil() end, Opaques);
@@ -1666,25 +1645,6 @@ type(lists, zipwith3, 4, Xs, Opaques) ->
fun ([F,_As,_Bs,_Cs]) -> t_sup(t_list(t_fun_range(F, Opaques)),
t_nil()) end, Opaques);
-%%-- string -------------------------------------------------------------------
-type(string, chars, 2, Xs, Opaques) -> % NOTE: added to avoid loss of info
- strict(string, chars, 2, Xs, fun (_) -> t_string() end, Opaques);
-type(string, chars, 3, Xs, Opaques) -> % NOTE: added to avoid loss of info
- strict(string, chars, 3, Xs,
- fun ([Char, N, Tail]) ->
- case t_is_nil(Tail) of
- true ->
- type(string, chars, 2, [Char, N]);
- false ->
- case t_is_string(Tail) of
- true ->
- t_string();
- false ->
- t_sup(t_sup(t_string(), Tail), t_cons(Char, Tail))
- end
- end
- end, Opaques);
-
%%-----------------------------------------------------------------------------
type(M, F, A, Xs, _O) when is_atom(M), is_atom(F),
is_integer(A), 0 =< A, A =< 255 ->
@@ -2289,8 +2249,6 @@ arg_types(erlang, bit_size, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, byte_size, 1) ->
[t_binary()];
-arg_types(erlang, disconnect_node, 1) ->
- [t_node()];
arg_types(erlang, halt, 0) ->
[];
arg_types(erlang, halt, 1) ->
@@ -2310,17 +2268,11 @@ arg_types(erlang, element, 2) ->
%% Guard bif, needs to be here.
arg_types(erlang, float, 1) ->
[t_number()];
-arg_types(erlang, fun_info, 1) ->
- [t_fun()];
-arg_types(erlang, get_cookie, 0) ->
- [];
%% Guard bif, needs to be here.
arg_types(erlang, hd, 1) ->
[t_cons()];
arg_types(erlang, info, 1) ->
arg_types(erlang, system_info, 1); % alias
-arg_types(erlang, integer_to_list, 2) ->
- [t_integer(), t_from_range(2, 36)];
arg_types(erlang, is_atom, 1) ->
[t_any()];
arg_types(erlang, is_binary, 1) ->
@@ -2361,12 +2313,12 @@ arg_types(erlang, length, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, map_size, 1) ->
[t_map()];
+arg_types(erlang, make_fun, 3) ->
+ [t_atom(), t_atom(), t_arity()];
arg_types(erlang, make_tuple, 2) ->
[t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument
arg_types(erlang, make_tuple, 3) ->
[t_non_neg_fixnum(), t_any(), t_list(t_tuple([t_pos_integer(), t_any()]))];
-arg_types(erlang, memory, 0) ->
- [];
arg_types(erlang, nif_error, 1) ->
[t_any()];
arg_types(erlang, nif_error, 2) ->
@@ -2383,29 +2335,13 @@ arg_types(erlang, round, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, self, 0) ->
[];
-arg_types(erlang, set_cookie, 2) ->
- [t_node(), t_atom()];
arg_types(erlang, setelement, 3) ->
[t_pos_integer(), t_tuple(), t_any()];
%% Guard bif, needs to be here.
arg_types(erlang, size, 1) ->
[t_sup(t_tuple(), t_binary())];
-arg_types(erlang, spawn, 1) -> %% TODO: Tuple?
- [t_fun()];
-arg_types(erlang, spawn, 2) -> %% TODO: Tuple?
- [t_node(), t_fun()];
-arg_types(erlang, spawn, 4) -> %% TODO: Tuple?
- [t_node(), t_atom(), t_atom(), t_list()];
-arg_types(erlang, spawn_link, 1) ->
- arg_types(erlang, spawn, 1); % same
-arg_types(erlang, spawn_link, 2) ->
- arg_types(erlang, spawn, 2); % same
-arg_types(erlang, spawn_link, 4) ->
- arg_types(erlang, spawn, 4); % same
arg_types(erlang, subtract, 2) ->
arg_types(erlang, '--', 2);
-arg_types(erlang, suspend_process, 1) ->
- [t_pid()];
arg_types(erlang, system_info, 1) ->
[t_sup([t_atom(), % documented
t_tuple([t_atom(), t_any()]), % documented
@@ -2424,11 +2360,6 @@ arg_types(erlang, tuple_size, 1) ->
[t_tuple()];
arg_types(erlang, tuple_to_list, 1) ->
[t_tuple()];
-arg_types(erlang, yield, 0) ->
- [];
-%%------- ets -----------------------------------------------------------------
-arg_types(ets, rename, 2) ->
- [t_atom(), t_atom()];
%%------- hipe_bifs -----------------------------------------------------------
arg_types(hipe_bifs, add_ref, 2) ->
[t_mfa(), t_tuple([t_mfa(),
@@ -2625,13 +2556,6 @@ arg_types(lists, zipwith, 3) ->
[t_fun([t_any(), t_any()], t_any()), t_list(), t_list()];
arg_types(lists, zipwith3, 4) ->
[t_fun([t_any(), t_any(), t_any()], t_any()), t_list(), t_list(), t_list()];
-
-%%------- string --------------------------------------------------------------
-arg_types(string, chars, 2) ->
- [t_char(), t_non_neg_integer()];
-arg_types(string, chars, 3) ->
- [t_char(), t_non_neg_integer(), t_any()];
-%%-----------------------------------------------------------------------------
arg_types(M, F, A) when is_atom(M), is_atom(F),
is_integer(A), 0 =< A, A =< 255 ->
unknown. % safe approximation for all functions.
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index cd2d2fe207..ab5a57dc3d 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -140,7 +140,6 @@
t_is_port/1, t_is_port/2,
t_is_maybe_improper_list/1, t_is_maybe_improper_list/2,
t_is_reference/1, t_is_reference/2,
- t_is_remote/1,
t_is_string/1,
t_is_subtype/2,
t_is_tuple/1, t_is_tuple/2,
@@ -180,7 +179,6 @@
%% t_maybe_improper_list/2,
t_product/1,
t_reference/0,
- t_remote/3,
t_string/0,
t_struct_from_opaque/2,
t_subst/2,
@@ -208,7 +206,6 @@
type_is_defined/4,
record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
- subst_all_remote/2,
lift_list_to_pos_empty/1, lift_list_to_pos_empty/2,
is_opaque_type/2,
is_erl_type/1,
@@ -280,7 +277,6 @@
-define(number_tag, number).
-define(opaque_tag, opaque).
-define(product_tag, product).
--define(remote_tag, remote).
-define(tuple_set_tag, tuple_set).
-define(tuple_tag, tuple).
-define(union_tag, union).
@@ -288,7 +284,7 @@
-type tag() :: ?atom_tag | ?binary_tag | ?function_tag | ?identifier_tag
| ?list_tag | ?map_tag | ?matchstate_tag | ?nil_tag | ?number_tag
- | ?opaque_tag | ?product_tag | ?remote_tag
+ | ?opaque_tag | ?product_tag
| ?tuple_tag | ?tuple_set_tag | ?union_tag | ?var_tag.
-define(float_qual, float).
@@ -330,7 +326,6 @@
%% was updated to 2.7 due to this change.
-record(opaque, {mod :: module(), name :: atom(),
args = [] :: [erl_type()], struct :: erl_type()}).
--record(remote, {mod:: module(), name :: atom(), args = [] :: [erl_type()]}).
-define(atom(Set), #c{tag=?atom_tag, elements=Set}).
-define(bitstr(Unit, Base), #c{tag=?binary_tag, elements=[Unit,Base]}).
@@ -350,7 +345,6 @@
-define(map(Pairs), #c{tag=?map_tag, elements=Pairs}).
-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}).
-define(tuple(Types, Arity, Qual), #c{tag=?tuple_tag, elements=Types,
qualifier={Arity, Qual}}).
-define(tuple_set(Tuples), #c{tag=?tuple_set_tag, elements=Tuples}).
@@ -380,19 +374,18 @@
%% Unions
%%
--define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_,_]=List}).
-
--define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
--define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
--define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
--define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
--define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
--define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
--define(remote_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
--define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
+-define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_]=List}).
+
+-define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
+-define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
+-define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
+-define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
+-define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
+-define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
+-define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
+-define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
-define(integer_union(T), ?number_union(T)).
-define(float_union(T), ?number_union(T)).
-define(nil_union(T), ?list_union(T)).
@@ -679,8 +672,8 @@ list_decorate(List, L, Opaques) ->
union_decorate(U1, U2, Opaques) ->
Union = union_decorate(U1, U2, Opaques, 0, []),
- [A,B,F,I,L,N,T,M,_,_R,Map] = U1,
- [_,_,_,_,_,_,_,_,Opaque,_,_] = U2,
+ [A,B,F,I,L,N,T,M,_,Map] = U1,
+ [_,_,_,_,_,_,_,_,Opaque,_] = U2,
List = [A,B,F,I,L,N,T,M,Map],
DecList = [Dec ||
E <- List,
@@ -792,21 +785,6 @@ list_struct_from_opaque(Types, Opaques) ->
[t_struct_from_opaque(Type, Opaques) || Type <- Types].
%%-----------------------------------------------------------------------------
-%% Remote types: these types are used for preprocessing;
-%% they should never reach the analysis stage.
-
--spec t_remote(atom(), atom(), [erl_type()]) -> erl_type().
-
-t_remote(Mod, Name, Args) ->
- ?remote(set_singleton(#remote{mod = Mod, name = Name, args = Args})).
-
--spec t_is_remote(erl_type()) -> boolean().
-
-t_is_remote(Type) ->
- do_opaque(Type, 'universe', fun is_remote/1).
-
-is_remote(?remote(_)) -> true;
-is_remote(_) -> false.
-type mod_records() :: dict:dict(module(), type_table()).
@@ -2178,8 +2156,6 @@ t_sup(?opaque(Set1), ?opaque(Set2)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
%%t_sup(T1, T2=?opaque(_,_,_)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
-t_sup(?remote(Set1), ?remote(Set2)) ->
- ?remote(set_union_no_limit(Set1, Set2));
t_sup(?matchstate(Pres1, Slots1), ?matchstate(Pres2, Slots2)) ->
?matchstate(t_sup(Pres1, Pres2), t_sup(Slots1, Slots2));
t_sup(?nil, ?nil) -> ?nil;
@@ -2373,7 +2349,6 @@ force_union(T = ?list(_, _, _)) -> ?list_union(T);
force_union(T = ?nil) -> ?list_union(T);
force_union(T = ?number(_, _)) -> ?number_union(T);
force_union(T = ?opaque(_)) -> ?opaque_union(T);
-force_union(T = ?remote(_)) -> ?remote_union(T);
force_union(T = ?map(_)) -> ?map_union(T);
force_union(T = ?tuple(_, _, _)) -> ?tuple_union(T);
force_union(T = ?tuple_set(_)) -> ?tuple_union(T);
@@ -2880,8 +2855,8 @@ inf_tuples_in_sets2(_, [], Acc, _Opaques) -> lists:reverse(Acc).
inf_union(U1, U2, Opaques) ->
OpaqueFun =
fun(Union1, Union2, InfFun) ->
- [_,_,_,_,_,_,_,_,Opaque,_,_] = Union1,
- [A,B,F,I,L,N,T,M,_,_R,Map] = Union2,
+ [_,_,_,_,_,_,_,_,Opaque,_] = Union1,
+ [A,B,F,I,L,N,T,M,_,Map] = Union2,
List = [A,B,F,I,L,N,T,M,Map],
inf_union_collect(List, Opaque, InfFun, [], [])
end,
@@ -3060,18 +3035,6 @@ t_subst_aux(?union(List), VarMap) ->
?union([t_subst_aux(E, VarMap) || E <- List]);
t_subst_aux(T, _VarMap) ->
T.
-
--spec subst_all_remote(erl_type(), erl_type()) -> erl_type().
-
-subst_all_remote(Type0, Substitute) ->
- Map =
- fun(Type) ->
- case t_is_remote(Type) of
- true -> Substitute;
- false -> Type
- end
- end,
- t_map(Map, Type0).
%%-----------------------------------------------------------------------------
%% Unification
@@ -3175,11 +3138,11 @@ unify_union1(?union(List), T1, T2) ->
end.
unify_union(List) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> no;
true ->
S = t_opaque_structure(O),
- {yes, t_sup([A,B,F,I,L,N,T,M,S,R,Map])}
+ {yes, t_sup([A,B,F,I,L,N,T,M,S,Map])}
end.
-spec is_opaque_type(erl_type(), [erl_type()]) -> boolean().
@@ -3537,10 +3500,10 @@ t_subtract_lists([], [], Acc) ->
-spec subtract_union([erl_type(),...], [erl_type(),...]) -> erl_type().
subtract_union(U1, U2) ->
- [A1,B1,F1,I1,L1,N1,T1,M1,O1,R1,Map1] = U1,
- [A2,B2,F2,I2,L2,N2,T2,M2,O2,R2,Map2] = U2,
- List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,R1,Map1],
- List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,R2,Map2],
+ [A1,B1,F1,I1,L1,N1,T1,M1,O1,Map1] = U1,
+ [A2,B2,F2,I2,L2,N2,T2,M2,O2,Map2] = U2,
+ List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,Map1],
+ List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,Map2],
Sub1 = subtract_union(List1, List2, 0, []),
O = if O1 =:= ?none -> O1;
true -> t_subtract(O1, ?union(U2))
@@ -3656,7 +3619,7 @@ t_unopaque(?product(Types), Opaques) ->
?product([t_unopaque(T, Opaques) || T <- Types]);
t_unopaque(?function(Domain, Range), Opaques) ->
?function(t_unopaque(Domain, Opaques), t_unopaque(Range, Opaques));
-t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) ->
+t_unopaque(?union([A,B,F,I,L,N,T,M,O,Map]), Opaques) ->
UL = t_unopaque(L, Opaques),
UT = t_unopaque(T, Opaques),
UF = t_unopaque(F, Opaques),
@@ -3665,7 +3628,7 @@ t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) ->
?opaque(_) = O1 -> {O1, []};
Type -> {?none, [Type]}
end,
- t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,R,UMap])|UO]);
+ t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,UMap])|UO]);
t_unopaque(T, _) ->
T.
@@ -3932,16 +3895,6 @@ t_to_string(?float, _RecDict) -> "float()";
t_to_string(?number(?any, ?unknown_qual), _RecDict) -> "number()";
t_to_string(?product(List), RecDict) ->
"<" ++ comma_sequence(List, RecDict) ++ ">";
-t_to_string(?remote(Set), RecDict) ->
- string:join([case Args =:= [] of
- true -> flat_format("~w:~w()", [Mod, Name]);
- false ->
- ArgString = comma_sequence(Args, RecDict),
- flat_format("~w:~w(~s)", [Mod, Name, ArgString])
- end
- || #remote{mod = Mod, name = Name, args = Args} <-
- set_to_list(Set)],
- " | ");
t_to_string(?map(Pairs), RecDict) ->
"#{" ++ map_pairs_to_string(Pairs,RecDict) ++ "}";
t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()";
@@ -3974,18 +3927,17 @@ record_to_string(Tag, [_|Fields], FieldNames, RecDict) ->
FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []),
"#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}".
-record_fields_to_string([F|Fs], [{FName, _Abstr, _DefType}|FDefs],
+record_fields_to_string([F|Fs], [{FName, _Abstr, DefType}|FDefs],
RecDict, Acc) ->
NewAcc =
- case t_is_equal(F, t_any()) orelse t_is_any_atom('undefined', F) of
+ case
+ t_is_equal(F, t_any()) orelse
+ (t_is_any_atom('undefined', F) andalso
+ not t_is_none(t_inf(F, DefType)))
+ of
true -> Acc;
false ->
StrFV = atom_to_string(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,
record_fields_to_string(Fs, FDefs, RecDict, NewAcc);
@@ -4825,13 +4777,13 @@ do_opaque(?opaque(_) = Type, Opaques, Pred) ->
false -> Pred(Type)
end;
do_opaque(?union(List) = Type, Opaques, Pred) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> Pred(Type);
true ->
case Opaques =:= 'universe' orelse is_opaque_type(O, Opaques) of
true ->
S = t_opaque_structure(O),
- do_opaque(t_sup([A,B,F,I,L,N,T,M,S,R,Map]), Opaques, Pred);
+ do_opaque(t_sup([A,B,F,I,L,N,T,M,S,Map]), Opaques, Pred);
false -> Pred(Type)
end
end;
@@ -4865,10 +4817,6 @@ set_union(S1, S2) ->
_ -> ?any
end.
-set_union_no_limit(?any, _) -> ?any;
-set_union_no_limit(_, ?any) -> ?any;
-set_union_no_limit(S1, S2) -> ordsets:union(S1, S2).
-
%% The intersection and subtraction can return ?none.
%% This should always be handled right away since ?none is not a valid set.
%% However, ?any is considered a valid set.
diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml
index 98fec900af..bf4bdbb3b3 100644
--- a/lib/hipe/doc/src/hipe_app.xml
+++ b/lib/hipe/doc/src/hipe_app.xml
@@ -37,15 +37,14 @@
<description>
<p>
The normal way to native-compile an Erlang module using HiPE is to include the atom native
- in the Erlang compiler options, as in:
- <code>
- 1> <input>c(my_module, [native]).</input></code>
- Options to the HiPE compiler are then passed as follows:
- <code>
- 1> <input>c(my_module, [native,{hipe,Options}]).</input></code>
- For on-line help in the Erlang shell, call <c>hipe:help()</c>.
- Details on HiPE compiler options are given by <c>hipe:help_options()</c>.
- </p>
+ in the Erlang compiler options, as in:</p>
+ <pre>
+ 1> <input>c(my_module, [native]).</input></pre>
+ <p>Options to the HiPE compiler are then passed as follows:</p>
+ <pre>
+ 1> <input>c(my_module, [native,{hipe,Options}]).</input></pre>
+ <p>For on-line help in the Erlang shell, call <c>hipe:help()</c>.
+ Details on HiPE compiler options are given by <c>hipe:help_options()</c>.</p>
</description>
<section>
<title>SEE ALSO</title>
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index a463b421a8..b5b13948e9 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -31,6 +31,51 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.14</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix hipe bug causing segfaults when native code
+ constructs binaries starting with a zero-length integer
+ field.</p>
+ <p>
+ Own Id: OTP-13048</p>
+ </item>
+ <item>
+ <p>
+ Reintroduce the <c>erlang:make_fun/3</c> BIF in
+ erl_bif_types.</p>
+ <p>
+ Own Id: OTP-13068</p>
+ </item>
+ <item>
+ <p>
+ In certain cases of matching with very big binaries, the
+ HiPE compiler generated code that would fail the match,
+ even in cases that the matching was successful. The
+ problem was more quite noticeable on 32-bit platforms.</p>
+ <p>
+ Own Id: OTP-13092</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ mikpe/hipe_x86_signal-musl-support</p>
+ <p>
+ Own Id: OTP-13159</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.13</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -319,22 +364,28 @@
<p>
EEP43: New data type - Maps</p>
<p>
- With Maps you may for instance: <taglist> <item><c>M0 =
- #{ a =&gt; 1, b =&gt; 2}, % create
- associations</c></item> <item><c>M1 = M0#{ a := 10 }, %
- update values</c></item> <item><c>M2 = M1#{ "hi" =&gt;
- "hello"}, % add new associations</c></item> <item><c>#{
- "hi" := V1, a := V2, b := V3} = M2. % match keys with
- values</c></item> </taglist></p>
+ With Maps you may for instance:</p>
+ <taglist>
+ <tag/> <item><c>M0 = #{ a =&gt; 1, b =&gt; 2}, % create
+ associations</c></item>
+ <tag/><item><c>M1 = M0#{ a := 10 }, % update values</c></item>
+ <tag/><item><c>M2 = M1#{ "hi" =&gt;
+ "hello"}, % add new associations</c></item>
+ <tag/><item><c>#{ "hi" := V1, a := V2, b := V3} = M2.
+ % match keys with values</c></item>
+ </taglist>
<p>
For information on how to use Maps please see Map Expressions in the
<seealso marker="doc/reference_manual:expressions#map_expressions">
Reference Manual</seealso>.</p>
<p>
The current implementation is without the following
- features: <taglist> <item>No variable keys</item>
- <item>No single value access</item> <item>No map
- comprehensions</item> </taglist></p>
+ features:</p>
+ <taglist>
+ <tag/><item>No variable keys</item>
+ <tag/><item>No single value access</item>
+ <tag/><item>No map comprehensions</item>
+ </taglist>
<p>
Note that Maps is <em>experimental</em> during OTP 17.0.</p>
<p>
@@ -602,19 +653,17 @@
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
- <p>
<list> <item><p>No warnings for underspecs with remote
types</p></item> <item><p> Fix crash in Typer</p></item>
<item><p>Fix Dialyzer's warning for its own
code</p></item> <item><p>Fix Dialyzer's warnings in
HiPE</p></item> <item><p>Add file/line info in a
particular Dialyzer crash</p></item> <item><p>Update
- inets test results</p></item> </list></p>
+ inets test results</p></item> </list>
<p>
Own Id: OTP-9758</p>
</item>
<item>
- <p>
<list> <item><p>Correct callback spec in application
module</p></item> <item><p>Refine warning about callback
specs with extra ranges</p></item> <item><p>Cleanup
@@ -625,7 +674,7 @@
analysis</p></item> <item><p>Fix crash in
Dialyzer</p></item> <item><p>Variable substitution was
not generalizing any unknown variables.</p></item>
- </list></p>
+ </list>
<p>
Own Id: OTP-9776</p>
</item>
diff --git a/lib/hipe/flow/cfg.hrl b/lib/hipe/flow/cfg.hrl
index f79fff4efe..641ec102db 100644
--- a/lib/hipe/flow/cfg.hrl
+++ b/lib/hipe/flow/cfg.hrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,11 +34,13 @@
%%
-record(cfg_info, {'fun' :: mfa(),
start_label :: cfg_lbl(),
+ %% TODO: merge is_closure and closure_arity into one field
is_closure :: boolean(),
- closure_arity :: arity(),
+ closure_arity = none :: 'none' | arity(),
is_leaf :: boolean(),
params, % :: list()
info = []}). %% this field seems not needed; take out??
+-type cfg_info() :: #cfg_info{}.
%%
%% Data is a triple with a dict of constants, a list of labels and an integer
@@ -49,6 +51,6 @@
%% The following is to be used by other modules
%%
-record(cfg, {table = gb_trees:empty() :: gb_trees:tree(),
- info :: #cfg_info{},
+ info :: cfg_info(),
data :: cfg_data()}).
-type cfg() :: #cfg{}.
diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl
index 5c7003b0ed..07d230491d 100644
--- a/lib/hipe/icode/hipe_icode.erl
+++ b/lib/hipe/icode/hipe_icode.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -631,59 +631,59 @@ mk_icode(Fun, Params, IsClosure, IsLeaf, Code, VarRange, LabelRange) ->
-spec mk_icode(mfa(), [icode_var()], boolean(), boolean(), [icode_instr()],
hipe_consttab(), {non_neg_integer(),non_neg_integer()},
- {icode_lbl(),icode_lbl()}) -> #icode{}.
+ {icode_lbl(),icode_lbl()}) -> icode().
mk_icode(Fun, Params, IsClosure, IsLeaf, Code, Data, VarRange, LabelRange) ->
#icode{'fun'=Fun, params=Params, code=Code,
data=Data, is_closure=IsClosure, is_leaf=IsLeaf,
var_range=VarRange, label_range=LabelRange}.
--spec icode_fun(#icode{}) -> mfa().
+-spec icode_fun(icode()) -> mfa().
icode_fun(#icode{'fun' = MFA}) -> MFA.
--spec icode_params(#icode{}) -> [icode_var()].
+-spec icode_params(icode()) -> [icode_var()].
icode_params(#icode{params = Params}) -> Params.
--spec icode_params_update(#icode{}, [icode_var()]) -> #icode{}.
+-spec icode_params_update(icode(), [icode_var()]) -> icode().
icode_params_update(Icode, Params) ->
Icode#icode{params = Params}.
--spec icode_is_closure(#icode{}) -> boolean().
+-spec icode_is_closure(icode()) -> boolean().
icode_is_closure(#icode{is_closure = Closure}) -> Closure.
--spec icode_is_leaf(#icode{}) -> boolean().
+-spec icode_is_leaf(icode()) -> boolean().
icode_is_leaf(#icode{is_leaf = Leaf}) -> Leaf.
--spec icode_code(#icode{}) -> icode_instrs().
+-spec icode_code(icode()) -> icode_instrs().
icode_code(#icode{code = Code}) -> Code.
--spec icode_code_update(#icode{}, icode_instrs()) -> #icode{}.
+-spec icode_code_update(icode(), icode_instrs()) -> icode().
icode_code_update(Icode, NewCode) ->
Vmax = highest_var(NewCode),
Lmax = highest_label(NewCode),
Icode#icode{code = NewCode, var_range = {0,Vmax}, label_range = {0,Lmax}}.
--spec icode_data(#icode{}) -> hipe_consttab().
+-spec icode_data(icode()) -> hipe_consttab().
icode_data(#icode{data=Data}) -> Data.
-%% %% -spec icode_data_update(#icode{}, hipe_consttab()) -> #icode{}.
+%% %% -spec icode_data_update(icode(), hipe_consttab()) -> icode().
%% icode_data_update(Icode, NewData) -> Icode#icode{data=NewData}.
--spec icode_var_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}.
+-spec icode_var_range(icode()) -> {non_neg_integer(), non_neg_integer()}.
icode_var_range(#icode{var_range = VarRange}) -> VarRange.
--spec icode_label_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}.
+-spec icode_label_range(icode()) -> {non_neg_integer(), non_neg_integer()}.
icode_label_range(#icode{label_range = LabelRange}) -> LabelRange.
--spec icode_info(#icode{}) -> icode_info().
+-spec icode_info(icode()) -> icode_info().
icode_info(#icode{info = Info}) -> Info.
--spec icode_info_update(#icode{}, icode_info()) -> #icode{}.
+-spec icode_info_update(icode(), icode_info()) -> icode().
icode_info_update(Icode, Info) -> Icode#icode{info = Info}.
--spec icode_closure_arity(#icode{}) -> arity().
+-spec icode_closure_arity(icode()) -> arity().
icode_closure_arity(#icode{closure_arity = Arity}) -> Arity.
--spec icode_closure_arity_update(#icode{}, arity()) -> #icode{}.
+-spec icode_closure_arity_update(icode(), arity()) -> icode().
icode_closure_arity_update(Icode, Arity) -> Icode#icode{closure_arity = Arity}.
@@ -1376,12 +1376,12 @@ remove_constants(L) ->
%% Substitution: replace occurrences of X by Y if {X,Y} is in the
%% Subst_list.
--spec subst([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst([{_,_}], I) -> I when I :: icode_instr().
subst(Subst, I) ->
subst_defines(Subst, subst_uses(Subst, I)).
--spec subst_uses([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_uses([{_,_}], I) -> I when I :: icode_instr().
subst_uses(Subst, I) ->
case I of
@@ -1405,7 +1405,7 @@ subst_uses(Subst, I) ->
#icode_label{} -> I
end.
--spec subst_defines([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_defines([{_,_}], I) -> I when I :: icode_instr().
subst_defines(Subst, I) ->
case I of
@@ -1709,7 +1709,7 @@ mk_new_label() ->
%% @doc Removes comments from Icode.
%%
--spec strip_comments(#icode{}) -> #icode{}.
+-spec strip_comments(icode()) -> icode().
strip_comments(ICode) ->
icode_code_update(ICode, no_comments(icode_code(ICode))).
diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl
index 9b24c4914e..3bb7bae019 100644
--- a/lib/hipe/icode/hipe_icode.hrl
+++ b/lib/hipe/icode/hipe_icode.hrl
@@ -170,8 +170,9 @@
-record(icode, {'fun' :: mfa(),
params :: [icode_var()],
+ %% TODO: merge is_closure and closure_arity into one field
is_closure :: boolean(),
- closure_arity :: arity(),
+ closure_arity = none :: 'none' | arity(),
is_leaf :: boolean(),
code = [] :: icode_instrs(),
data :: hipe_consttab(),
diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl
index 41556ab80f..f03ce2faaa 100644
--- a/lib/hipe/icode/hipe_icode_exceptions.erl
+++ b/lib/hipe/icode/hipe_icode_exceptions.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@
%%----------------------------------------------------------------------------
--spec fix_catches(#cfg{}) -> #cfg{}.
+-spec fix_catches(cfg()) -> cfg().
fix_catches(CFG) ->
{Map, State} = build_mapping(find_catches(init_state(CFG))),
@@ -393,10 +393,10 @@ get_renaming(C, Map) ->
%%---------------------------------------------------------------------
%% State abstraction
--record(state, {cfg :: #cfg{},
+-record(state, {cfg :: cfg(),
changed = false :: boolean(),
- succ :: #cfg{},
- pred :: #cfg{},
+ succ :: cfg(),
+ pred :: cfg(),
start_labels :: [icode_lbl(),...],
visited = hipe_icode_cfg:none_visited() :: gb_sets:set(),
out = gb_trees:empty() :: gb_trees:tree(),
@@ -404,13 +404,8 @@ get_renaming(C, Map) ->
}).
init_state(CFG) ->
- State = #state{cfg = CFG},
- refresh_state_cache(State).
-
-refresh_state_cache(State) ->
- CFG = State#state.cfg,
SLs = [hipe_icode_cfg:start_label(CFG)],
- State#state{succ = CFG, pred = CFG, start_labels = SLs}.
+ #state{cfg = CFG, succ = CFG, pred = CFG, start_labels = SLs}.
get_cfg(State) ->
State#state.cfg.
@@ -466,7 +461,8 @@ get_bb_code(L, State) ->
set_bb_code(L, Code, State) ->
CFG = State#state.cfg,
CFG1 = hipe_icode_cfg:bb_add(CFG, L, hipe_bb:mk_bb(Code)),
- refresh_state_cache(State#state{cfg = CFG1}).
+ SLs = [hipe_icode_cfg:start_label(CFG1)],
+ State#state{cfg = CFG1, succ = CFG1, pred = CFG1, start_labels = SLs}.
get_new_catches_in(L, State) ->
Ps = get_pred(L, State),
diff --git a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
index e350a6ff18..7613024787 100644
--- a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
+++ b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -314,7 +314,7 @@ node_create(Label, Pred, Succ) ->
%% tree - the tree of nodes, with labels as keys and node records as values
-record(nodes, {
- domtree :: hipe_dominators:domTree(),
+ domtree = none :: 'none' | hipe_dominators:domTree(),
labels = none :: 'none' | [icode_lbl()],
postorder = none :: 'none' | [icode_lbl()],
start_label = none :: 'none' | icode_lbl(),
@@ -390,7 +390,7 @@ update_del_red_test_set(Update) ->
%%-----------------------------------------------------------------------------
%% Main function called from the hipe_main module
--spec struct_reuse(#cfg{}) -> #cfg{}.
+-spec struct_reuse(cfg()) -> cfg().
struct_reuse(CFG) ->
%% debug_init_case_count(?SR_INSTR_TYPE),
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index 1a4bbf179f..0e32da1d36 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -764,7 +764,8 @@ finalize(OrigList, Mod, Exports, WholeModule, Opts) ->
finalize_fun(MfaIcodeList, Exports, Opts) ->
case proplists:get_value(concurrent_comp, Opts) of
FalseVal when (FalseVal =:= undefined) orelse (FalseVal =:= false) ->
- [finalize_fun_sequential(MFAIcode, Opts, #comp_servers{})
+ NoServers = #comp_servers{pp_server = none, range = none, type = none},
+ [finalize_fun_sequential(MFAIcode, Opts, NoServers)
|| {_MFA, _Icode} = MFAIcode <- MfaIcodeList];
TrueVal when (TrueVal =:= true) orelse (TrueVal =:= debug) ->
finalize_fun_concurrent(MfaIcodeList, Exports, Opts)
diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src
index ba27878a84..3be824ac34 100644
--- a/lib/hipe/main/hipe.hrl.src
+++ b/lib/hipe/main/hipe.hrl.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -299,7 +299,8 @@
%% Records defined in the hipe module used in other parts of the compiler
%%----------------------------------------------------------------------------
--record(comp_servers, {pp_server :: pid(), range :: pid(), type :: pid()}).
+-type mpid() :: 'none' | pid().
+-record(comp_servers, {pp_server :: mpid(), range :: mpid(), type :: mpid()}).
%%----------------------------------------------------------------------------
%% Basic types of the 'hipe' application used in other parts of the system
diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl
index 5753169961..be5050e155 100644
--- a/lib/hipe/main/hipe_main.erl
+++ b/lib/hipe/main/hipe_main.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@
%%=====================================================================
%% @spec compile_icode(MFA::mfa(),
-%% LinearIcode::#icode{},
+%% LinearIcode::icode(),
%% CompilerOptions::comp_options(),
%% CompServers::#comp_servers()) ->
%% {native,Platform,{unprofiled,NativeCode}} | {rtl,RTLCode}
@@ -69,7 +69,7 @@
%% generated). The compiler options must have already been expanded
%% (cf. `<a href="hipe.html">hipe:expand_options</a>'). </p>
--spec compile_icode(mfa(), #icode{}, comp_options(), #comp_servers{}) ->
+-spec compile_icode(mfa(), icode(), comp_options(), #comp_servers{}) ->
comp_icode_ret().
compile_icode(MFA, LinearIcode, Options, Servers) ->
@@ -230,10 +230,12 @@ get_pp_module(icode_liveness) -> hipe_icode_liveness;
get_pp_module(rtl_liveness) -> hipe_rtl_liveness.
perform_io(no_fun, _) -> ok;
-perform_io(Fun,PPServer) when is_pid(PPServer) ->
- PPServer ! {print,Fun};
-perform_io(Fun, undefined) ->
- Fun().
+perform_io(Fun, PPServer) when is_pid(PPServer) ->
+ PPServer ! {print, Fun},
+ ok;
+perform_io(Fun, none) ->
+ Fun(),
+ ok.
%%--------------------------------------------------------------------
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index d2517b13fc..1bf52fe312 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -75,7 +75,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
include ../native.mk
-ERL_COMPILE_FLAGS += +inline +warn_unused_import +warn_exported_vars
+ERL_COMPILE_FLAGS += -Werror +inline +warn_unused_import +warn_exported_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/rtl/hipe_rtl_binary_construct.erl b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
index 40bd22aa8e..692bad7d96 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_construct.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1192,7 +1192,10 @@ copy_little_word(Base, Offset, NewOffset, Word) ->
hipe_rtl:mk_store(Base, TmpOffset, Word, byte),
hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(32))].
-copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) ->
+copy_offset_int_big(_Base, Offset, NewOffset, 0, _Tmp1) ->
+ [hipe_rtl:mk_move(NewOffset, Offset)];
+copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1)
+ when is_integer(Size), Size > 0 ->
Tmp2 = hipe_rtl:mk_new_reg(),
Tmp3 = hipe_rtl:mk_new_reg(),
Tmp4 = hipe_rtl:mk_new_reg(),
@@ -1203,7 +1206,7 @@ copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -
Tmp9 = hipe_rtl:mk_new_reg(),
OldByte = hipe_rtl:mk_new_reg(),
TmpOffset = hipe_rtl:mk_new_reg(),
- BranchLbl = hipe_rtl:mk_new_label(),
+ BranchLbl = hipe_rtl:mk_new_label(),
BodyLbl = hipe_rtl:mk_new_label(),
EndLbl = hipe_rtl:mk_new_label(),
NextLbl = hipe_rtl:mk_new_label(),
diff --git a/lib/hipe/rtl/hipe_rtl_binary_match.erl b/lib/hipe/rtl/hipe_rtl_binary_match.erl
index 364aab1b6f..51213b71d1 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_match.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_match.erl
@@ -2,7 +2,7 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
@@ -181,17 +181,20 @@ gen_rtl({bs_get_binary, Size, Flags}, [Dst, NewMs], Args,
[hipe_rtl:mk_goto(FalseLblName)];
false ->
Unsafe = unsafe(Flags),
- case Args of
- [Ms] ->
- SizeReg = hipe_rtl:mk_new_reg(),
- SizeCode = [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))];
- [Ms, BitsVar] ->
- {SizeCode, SizeReg} = make_size(Size, BitsVar, FalseLblName)
- end,
- InCode = get_binary(Dst, Ms, SizeReg, Unsafe,
+ {OldMs, SizeReg, SizeCode} =
+ case Args of
+ [Ms] ->
+ SzReg = hipe_rtl:mk_new_reg(),
+ SzCode = [hipe_rtl:mk_move(SzReg, hipe_rtl:mk_imm(Size))],
+ {Ms, SzReg, SzCode};
+ [Ms, BitsVar] ->
+ {SzCode, SzReg} = make_size(Size, BitsVar, FalseLblName),
+ {Ms, SzReg, SzCode}
+ end,
+ InCode = get_binary(Dst, OldMs, SizeReg, Unsafe,
TrueLblName, FalseLblName),
[hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE)] ++
- update_ms(NewMs, Ms) ++ SizeCode ++ InCode
+ update_ms(NewMs, OldMs) ++ SizeCode ++ InCode
end;
%% ----- bs_get_utf8 -----
gen_rtl(bs_get_utf8, [Dst, NewMs], [Ms], TrueLblName, FalseLblName) ->
@@ -230,14 +233,26 @@ gen_rtl({bs_skip_bits_all, Unit, _Flags}, Dst, [Ms],
skip_bits_all(Unit, Ms, TrueLblName, FalseLblName);
%% ----- bs_skip_bits -----
gen_rtl({bs_skip_bits, Bits}, Dst, [Ms|Args], TrueLblName, FalseLblName) ->
+ MaxValue = (1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE)),
opt_update_ms(Dst, Ms) ++
- case Args of
- [] ->
- skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName);
- [Arg] ->
- {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName),
- InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName),
- SizeCode ++ InCode
+ case Bits < MaxValue of
+ true ->
+ case Args of
+ [] ->
+ skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName);
+ [Arg] ->
+ {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName),
+ InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName),
+ SizeCode ++ InCode
+ end;
+ false -> % handle overflow case
+ case Args of
+ [] ->
+ [hipe_rtl:mk_goto(FalseLblName)];
+ [Arg] ->
+ [hipe_rtl:mk_branch(Arg, 'eq', hipe_tagscheme:mk_fixnum(0),
+ TrueLblName, FalseLblName, 0.5)]
+ end
end;
%% ----- bs_restore -----
gen_rtl({bs_restore, Slot}, [NewMs], [Ms], TrueLblName, _FalseLblName) ->
@@ -1086,23 +1101,47 @@ create_gcsafe_regs(0) ->
[].
first_part(Var, Register, FalseLblName) ->
- [SuccessLbl1, SuccessLbl2] = create_lbls(2),
- [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(SuccessLbl1),
- FalseLblName, 0.99),
- SuccessLbl1,
- hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)),
- hipe_rtl:label_name(SuccessLbl2), FalseLblName, 0.99),
- SuccessLbl2,
- hipe_tagscheme:untag_fixnum(Register, Var)].
+ [EndLbl] = create_lbls(1),
+ EndName = hipe_rtl:label_name(EndLbl),
+ first_part(Var, Register, FalseLblName, EndName, EndName, [EndLbl]).
+
+first_part(Var, Register, FalseLblName, TrueLblName, BigLblName, Tail) ->
+ [FixnumLbl, NotFixnumLbl, BignumLbl, SuccessLbl] = create_lbls(4),
+ [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(FixnumLbl),
+ hipe_rtl:label_name(NotFixnumLbl), 0.99),
+ FixnumLbl,
+ hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)),
+ hipe_rtl:label_name(SuccessLbl), FalseLblName,
+ 0.99),
+ SuccessLbl,
+ hipe_tagscheme:untag_fixnum(Register, Var),
+ hipe_rtl:mk_goto(TrueLblName),
+ NotFixnumLbl,
+ %% Since binaries are not allowed to be larger than 2^wordsize bits
+ %% and since bignum digits are words, we know that a bignum with an
+ %% arity larger than one can't match.
+ hipe_tagscheme:test_pos_bignum_arity(Var, 1, hipe_rtl:label_name(BignumLbl),
+ FalseLblName, 0.99),
+ BignumLbl,
+ hipe_tagscheme:unsafe_get_one_word_pos_bignum(Register, Var),
+ hipe_rtl:mk_goto(BigLblName) | Tail].
make_size(1, BitsVar, FalseLblName) ->
[DstReg] = create_regs(1),
{first_part(BitsVar, DstReg, FalseLblName), DstReg};
make_size(?BYTE_SIZE, BitsVar, FalseLblName) ->
[DstReg] = create_regs(1),
- Code =
- first_part(BitsVar, DstReg, FalseLblName) ++
- [hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))],
+ [FixnumLbl, BignumLbl] = create_lbls(2),
+ WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE,
+ FixnumLblName = hipe_rtl:label_name(FixnumLbl),
+ Tail = [BignumLbl,
+ hipe_rtl:mk_branch(DstReg, 'ltu',
+ hipe_rtl:mk_imm(1 bsl (WordBits - ?BYTE_SHIFT)),
+ FixnumLblName, FalseLblName, 0.99),
+ FixnumLbl,
+ hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))],
+ Code = first_part(BitsVar, DstReg, FalseLblName, FixnumLblName,
+ hipe_rtl:label_name(BignumLbl), Tail),
{Code, DstReg};
make_size(UnitImm, BitsVar, FalseLblName) ->
[DstReg] = create_regs(1),
@@ -1151,12 +1190,13 @@ floorlog2(X) ->
round(math:log(X)/math:log(2)-0.5).
set_high(X) ->
- set_high(X, 0).
+ WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE,
+ set_high(min(X, WordBits), WordBits, 0).
-set_high(0, Y) ->
+set_high(0, _, Y) ->
Y;
-set_high(X, Y) ->
- set_high(X-1, Y+(1 bsl (27-X))).
+set_high(X, WordBits, Y) ->
+ set_high(X-1, WordBits, Y+(1 bsl (WordBits-X))).
is_illegal_const(Const) ->
Const >= 1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE) orelse Const < 0.
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index 1bb4c3cc5f..d77078acb6 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,7 +41,8 @@
test_any_pid/4, test_any_port/4,
test_ref/4, test_fun/4, test_fun2/5, test_matchstate/4,
test_binary/4, test_bitstr/4, test_list/4, test_map/4,
- test_integer/4, test_number/4, test_tuple_N/5]).
+ test_integer/4, test_number/4, test_tuple_N/5,
+ test_pos_bignum_arity/5]).
-export([realtag_fixnum/2, tag_fixnum/2, realuntag_fixnum/2, untag_fixnum/2]).
-export([test_two_fixnums/3, test_fixnums/4, unsafe_fixnum_add/3,
unsafe_fixnum_sub/3,
@@ -53,9 +54,10 @@
-export([unsafe_closure_element/3]).
-export([mk_fun_header/0, tag_fun/2]).
-export([unsafe_untag_float/2, unsafe_tag_float/2]).
--export([mk_sub_binary/6,mk_sub_binary/7]).
+-export([mk_sub_binary/6, mk_sub_binary/7]).
-export([unsafe_mk_big/3, unsafe_load_float/3]).
--export([bignum_sizeneed/1,bignum_sizeneed_code/2, get_one_word_pos_bignum/3]).
+-export([bignum_sizeneed/1, bignum_sizeneed_code/2, get_one_word_pos_bignum/3,
+ unsafe_get_one_word_pos_bignum/2]).
-export([test_subbinary/3, test_heap_binary/3]).
-export([create_heap_binary/3, create_refc_binary/3, create_refc_binary/4]).
-export([create_matchstate/6, convert_matchstate/1, compare_matchstate/4]).
@@ -349,6 +351,15 @@ test_pos_bignum(X, TrueLab, FalseLab, Pred) ->
mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG,
TrueLab, FalseLab, Pred)].
+test_pos_bignum_arity(X, Arity, TrueLab, FalseLab, Pred) ->
+ Tmp = hipe_rtl:mk_new_reg_gcsafe(),
+ HalfTrueLab = hipe_rtl:mk_new_label(),
+ HeaderImm = hipe_rtl:mk_imm(mk_header(Arity, ?TAG_HEADER_POS_BIG)),
+ [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred),
+ HalfTrueLab,
+ get_header(Tmp, X),
+ hipe_rtl:mk_branch(Tmp, 'eq', HeaderImm, TrueLab, FalseLab, Pred)].
+
test_matchstate(X, TrueLab, FalseLab, Pred) ->
Tmp = hipe_rtl:mk_new_reg_gcsafe(),
HalfTrueLab = hipe_rtl:mk_new_label(),
@@ -963,13 +974,16 @@ get_one_word_pos_bignum(USize, Size, Fail) ->
Header = hipe_rtl:mk_new_reg(),
HalfLbl = hipe_rtl:mk_new_label(),
HalfLblName = hipe_rtl:label_name(HalfLbl),
- WordSize = hipe_rtl_arch:word_size(),
PosHead = hipe_rtl:mk_imm(mk_header(1, ?TAG_HEADER_POS_BIG)),
[get_header(Header, Size),
hipe_rtl:mk_branch(Header, eq, PosHead, HalfLblName, Fail),
- HalfLbl,
- hipe_rtl:mk_load(USize, Size, hipe_rtl:mk_imm(1*WordSize
- -?TAG_PRIMARY_BOXED))].
+ HalfLbl |
+ unsafe_get_one_word_pos_bignum(USize, Size)].
+
+unsafe_get_one_word_pos_bignum(USize, Size) ->
+ WordSize = hipe_rtl_arch:word_size(),
+ Imm = hipe_rtl:mk_imm(1*WordSize-?TAG_PRIMARY_BOXED),
+ [hipe_rtl:mk_load(USize, Size, Imm)].
-spec bignum_sizeneed(non_neg_integer()) -> non_neg_integer().
diff --git a/lib/hipe/test/bs_SUITE_data/bs_construct.erl b/lib/hipe/test/bs_SUITE_data/bs_construct.erl
index 9cc9ac848c..37a54c1981 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_construct.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_construct.erl
@@ -13,6 +13,7 @@ test() ->
ok = bs5(),
16#10000008 = bit_size(large_bin(1, 2, 3, 4)),
ok = bad_ones(),
+ ok = zero_width(),
ok.
%%--------------------------------------------------------------------
@@ -126,3 +127,18 @@ bad_ones() ->
Bin123 = <<1,2,3>>,
?FAIL(<<Bin123/float>>),
ok.
+
+%%--------------------------------------------------------------------
+%% Taken from the emulator bs_construct_SUITE - seg faulted till 18.1
+
+zero_width() ->
+ Z = id(0),
+ Small = id(42),
+ Big = id(1 bsl 128), % puts stuff on the heap
+ <<>> = <<Small:Z>>,
+ <<>> = <<Small:0>>,
+ <<>> = <<Big:Z>>,
+ <<>> = <<Big:0>>,
+ ok.
+
+id(X) -> X.
diff --git a/lib/hipe/test/bs_SUITE_data/bs_match.erl b/lib/hipe/test/bs_SUITE_data/bs_match.erl
index 7bc93a316b..b241ea8d35 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_match.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_match.erl
@@ -1,8 +1,8 @@
%%% -*- erlang-indent-level: 2 -*-
%%%-------------------------------------------------------------------
%%% File : bs_match.erl
-%%% Author : Per Gustafsson <[email protected]>
-%%% Purpose : Performs simple matching and construction of binaries
+%%% Authors : Per Gustafsson <[email protected]>, Kostis Sagonas <[email protected]>
+%%% Purpose : Tests matching and construction of binaries
%%% TODO : Add binary and float tests
%%% Created : 20 Feb 2004
%%%-------------------------------------------------------------------
@@ -13,7 +13,7 @@
test() ->
Funs = [fun test_aligned/0, fun test_unaligned/0,
fun test_zero_tail/0, fun test_integer_matching/0,
- fun test_writable_bin/0],
+ fun test_writable_bin/0, fun test_match_huge_bin/0],
lists:foreach(fun (F) -> ok = F() end, Funs).
%%-------------------------------------------------------------------
@@ -175,6 +175,9 @@ test_dynamic_integer_matching(N) ->
<<12:N/integer-little, 0:S>> = <<12:N/integer-little, 0:S>>,
ok.
+%%-------------------------------------------------------------------
+%% Test writable bin -- added by Sverker Eriksson
+
test_writable_bin() ->
test_writable_bin(<<>>, 0),
ok.
@@ -185,3 +188,102 @@ test_writable_bin(Bin0, N) when N < 128 ->
Bin1 = <<Bin0/binary, N>>,
<<_/utf8, _/binary>> = Bin1,
test_writable_bin(Bin1, N+1).
+
+%%-------------------------------------------------------------------
+%% Test matching with a huge bin -- taken from bs_match_bin_SUITE
+
+test_match_huge_bin() ->
+ Bin = <<0:(1 bsl 27),13:8>>,
+ skip_huge_bin_1(1 bsl 27, Bin),
+ 16777216 = match_huge_bin_1(1 bsl 27, Bin),
+ %% Test overflowing the size of a binary field.
+ nomatch = overflow_huge_bin_skip_32(Bin),
+ nomatch = overflow_huge_bin_32(Bin),
+ nomatch = overflow_huge_bin_skip_64(Bin),
+ nomatch = overflow_huge_bin_64(Bin),
+ %% Size in variable
+ ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok.
+
+overflow_huge_bin(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin(_, []) -> ok.
+
+overflow_huge_bin_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin_unit128(_, []) -> ok.
+
+skip_huge_bin_1(I, Bin) ->
+ <<_:I/binary-unit:1,13>> = Bin,
+ ok.
+
+match_huge_bin_1(I, Bin) ->
+ case Bin of
+ <<Val:I/binary-unit:1,13>> -> size(Val);
+ _ -> nomatch
+ end.
+
+overflow_huge_bin_skip_32(<<_:4294967296/binary,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_bin_skip_32(<<_:33554432/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_bin_skip_32(<<_:67108864/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_bin_skip_32(<<_:134217728/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_bin_skip_32(<<_:268435456/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_bin_skip_32(<<_:536870912/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_bin_skip_32(<<_:1073741824/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_bin_skip_32(<<_:2147483648/binary-unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_bin_skip_32(_) -> nomatch.
+
+overflow_huge_bin_32(<<Bin:4294967296/binary,_/binary>>) -> {1,Bin}; % 1 bsl 32
+overflow_huge_bin_32(<<Bin:33554432/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 25
+overflow_huge_bin_32(<<Bin:67108864/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 26
+overflow_huge_bin_32(<<Bin:134217728/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 27
+overflow_huge_bin_32(<<Bin:268435456/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 28
+overflow_huge_bin_32(<<Bin:536870912/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 29
+overflow_huge_bin_32(<<Bin:1073741824/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 30
+overflow_huge_bin_32(<<Bin:2147483648/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 31
+overflow_huge_bin_32(_) -> nomatch.
+
+overflow_huge_bin_skip_64(<<_:18446744073709551616/binary,0,_/binary>>) -> 1; % 1 bsl 64
+overflow_huge_bin_skip_64(<<_:144115188075855872/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 57
+overflow_huge_bin_skip_64(<<_:288230376151711744/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 58
+overflow_huge_bin_skip_64(<<_:576460752303423488/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 59
+overflow_huge_bin_skip_64(<<_:1152921504606846976/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 60
+overflow_huge_bin_skip_64(<<_:2305843009213693952/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 61
+overflow_huge_bin_skip_64(<<_:4611686018427387904/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 62
+overflow_huge_bin_skip_64(<<_:9223372036854775808/binary-unit:8,_/binary>>) -> 8; % 1 bsl 63
+overflow_huge_bin_skip_64(_) -> nomatch.
+
+overflow_huge_bin_64(<<Bin:18446744073709551616/binary,_/binary>>) -> {1,Bin}; % 1 bsl 64
+overflow_huge_bin_64(<<Bin:144115188075855872/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 57
+overflow_huge_bin_64(<<Bin:288230376151711744/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 58
+overflow_huge_bin_64(<<Bin:576460752303423488/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 59
+overflow_huge_bin_64(<<Bin:1152921504606846976/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 60
+overflow_huge_bin_64(<<Bin:2305843009213693952/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 61
+overflow_huge_bin_64(<<Bin:4611686018427387904/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 62
+overflow_huge_bin_64(<<Bin:9223372036854775808/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 63
+overflow_huge_bin_64(_) -> nomatch.
+
+id(I) -> I.
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 3ec9d7ee45..123792e708 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.13
+HIPE_VSN = 3.14