aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl11
-rw-r--r--lib/compiler/src/beam_ssa_type.erl16
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl14
-rw-r--r--lib/compiler/test/receive_SUITE.erl26
-rw-r--r--lib/crypto/c_src/cipher.c1
5 files changed, 57 insertions, 11 deletions
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index bf99e8fc26..9af72afca7 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -1415,12 +1415,15 @@ fix_receive([], _Defs, Blocks, Count) ->
find_loop_exit([L1,L2|_Ls], Blocks) ->
Path1 = beam_ssa:rpo([L1], Blocks),
Path2 = beam_ssa:rpo([L2], Blocks),
- find_loop_exit_1(reverse(Path1), reverse(Path2), none);
+ find_loop_exit_1(Path1, cerl_sets:from_list(Path2));
find_loop_exit(_, _) -> none.
-find_loop_exit_1([H|T1], [H|T2], _) ->
- find_loop_exit_1(T1, T2, H);
-find_loop_exit_1(_, _, Exit) -> Exit.
+find_loop_exit_1([H|T], OtherPath) ->
+ case cerl_sets:is_element(H, OtherPath) of
+ true -> H;
+ false -> find_loop_exit_1(T, OtherPath)
+ end;
+find_loop_exit_1([], _) -> none.
%% find_rm_blocks(StartLabel, Blocks) -> [Label].
%% Find all blocks that start with remove_message within the receive
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl
index fe229d25df..34cdd0d663 100644
--- a/lib/compiler/src/beam_ssa_type.erl
+++ b/lib/compiler/src/beam_ssa_type.erl
@@ -24,7 +24,7 @@
-include("beam_ssa_opt.hrl").
-import(lists, [all/2,any/2,droplast/1,foldl/3,last/1,member/2,
keyfind/3,partition/2,reverse/1,reverse/2,
- seq/2,sort/1,split/2]).
+ sort/1,split/2]).
-define(UNICODE_INT, #t_integer{elements={0,16#10FFFF}}).
@@ -874,11 +874,11 @@ type(call, [#b_remote{mod=#b_literal{val=Mod},
true ->
none
end;
- {#t_integer{elements={Min,Max}},
+ {#t_integer{elements={Min,_}}=IntType,
#t_tuple{elements=Es0,size=Size}=T} ->
- %% We know this will land between Min and Max, so kill the
- %% types for those indexes.
- Es = maps:without(seq(Min, Max), Es0),
+ %% Remove type information for all indices that
+ %% falls into the range of the integer.
+ Es = remove_element_info(IntType, Es0),
case T#t_tuple.exact of
false ->
T#t_tuple{elements=Es,size=max(Min, Size)};
@@ -1653,6 +1653,12 @@ get_literal_from_type(nil) ->
#b_literal{val=[]};
get_literal_from_type(_) -> none.
+remove_element_info(#t_integer{elements={Min,Max}}, Es) ->
+ foldl(fun(El, Acc) when Min =< El, El =< Max ->
+ maps:remove(El, Acc);
+ (_El, Acc) -> Acc
+ end, Es, maps:keys(Es)).
+
t_atom() ->
#t_atom{elements=any}.
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 0ddd91498e..2297c2e0f5 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -272,8 +272,22 @@ setelement(_Config) ->
T0 = id({a,42}),
{a,_} = T0,
{b,_} = setelement(1, T0, b),
+ {z,b} = do_setelement_1(<<(id(1)):32>>, {a,b}, z),
+ {new,two} = do_setelement_2(<<(id(1)):1>>, {one,two}, new),
ok.
+do_setelement_1(<<N:32>>, Tuple, NewValue) ->
+ _ = element(N, Tuple),
+ %% While updating the type for Tuple, beam_ssa_type would do:
+ %% maps:without(lists:seq(0, 4294967295), Elements)
+ setelement(N, Tuple, NewValue).
+
+do_setelement_2(<<N:1>>, Tuple, NewValue) ->
+ %% Cover the second clause in remove_element_info/2. The
+ %% type for the second element will be kept.
+ two = element(2, Tuple),
+ setelement(N, Tuple, NewValue).
+
cons(_Config) ->
[did] = cons(assigned, did),
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 0038eb1a4b..752491f0f8 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -26,7 +26,7 @@
init_per_testcase/2,end_per_testcase/2,
export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1,
wait/1,recv_in_try/1,double_recv/1,receive_var_zero/1,
- match_built_terms/1]).
+ match_built_terms/1,elusive_common_exit/1]).
-include_lib("common_test/include/ct.hrl").
@@ -47,7 +47,7 @@ groups() ->
[{p,test_lib:parallel(),
[recv,coverage,otp_7980,ref_opt,export,wait,
recv_in_try,double_recv,receive_var_zero,
- match_built_terms]}].
+ match_built_terms,elusive_common_exit]}].
init_per_suite(Config) ->
@@ -427,4 +427,26 @@ match_built_terms(Config) when is_list(Config) ->
?MATCH_BUILT_TERM(Ref, <<A, B>>),
?MATCH_BUILT_TERM(Ref, #{ 1 => A, 2 => B}).
+elusive_common_exit(_Config) ->
+ self() ! {1, a},
+ self() ! {2, b},
+ {[z], [{2,b},{1,a}]} = elusive_loop([x,y,z], 2, []),
+ ok.
+
+elusive_loop(List, 0, Results) ->
+ {List, Results};
+elusive_loop(List, ToReceive, Results) ->
+ {Result, RemList} =
+ receive
+ {_Pos, _R} = Res when List =/= [] ->
+ [_H|T] = List,
+ {Res, T};
+ {_Pos, _R} = Res when List =:= [] ->
+ {Res, []}
+ end,
+ %% beam_ssa_pre_codegen:fix_receives() would fail to find
+ %% the common exit block for this receive. That would mean
+ %% that it would not insert all necessary copy instructions.
+ elusive_loop(RemList, ToReceive-1, [Result | Results]).
+
id(I) -> I.
diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c
index 00072af632..0532fb7566 100644
--- a/lib/crypto/c_src/cipher.c
+++ b/lib/crypto/c_src/cipher.c
@@ -334,6 +334,7 @@ ERL_NIF_TERM cipher_types_as_list(ErlNifEnv* env)
continue;
if ((p->cipher.p != NULL) ||
+ (p->flags & AES_CTR_COMPAT) ||
(p->type.atom == atom_aes_ige256)) /* Special handling. Bad indeed... */
{
hd = enif_make_list_cell(env, p->type.atom, hd);