summaryrefslogtreecommitdiff
path: root/lib/compiler/test/beam_validator_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/test/beam_validator_SUITE.erl')
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl122
1 files changed, 104 insertions, 18 deletions
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 47970f3021..2092d7401a 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -41,8 +41,9 @@
missing_return_type/1,will_succeed/1,
bs_saved_position_units/1,parent_container/1,
container_performance/1,
- not_equal_inference/1,
- inert_update_type/1]).
+ infer_relops/1,
+ not_equal_inference/1,bad_bin_unit/1,singleton_inference/1,
+ inert_update_type/1,range_inference/1]).
-include_lib("common_test/include/ct.hrl").
@@ -77,9 +78,9 @@ groups() ->
receive_marker,safe_instructions,
missing_return_type,will_succeed,
bs_saved_position_units,parent_container,
- container_performance,
- not_equal_inference,
- inert_update_type]}].
+ container_performance,infer_relops,
+ not_equal_inference,bad_bin_unit,singleton_inference,
+ inert_update_type,range_inference]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -183,9 +184,11 @@ call_without_stack(Config) when is_list(Config) ->
merge_undefined(Config) when is_list(Config) ->
Errors = do_val(merge_undefined, Config),
[{{t,undecided,2},
- {{call_ext,2,{extfunc,debug,filter,2}},
- 22,
- {allocated,undecided}}},
+ {{label,11},
+ 19,
+ {unsafe_stack,{y,1},
+ #{{y,0} := uninitialized,
+ {y,1} := uninitialized}}}},
{{t,uninitialized,2},
{{call_ext,2,{extfunc,io,format,2}},
17,
@@ -324,7 +327,7 @@ state_after_fault_in_catch(Config) when is_list(Config) ->
no_exception_in_catch(Config) when is_list(Config) ->
Errors = do_val(no_exception_in_catch, Config),
[{{no_exception_in_catch,nested_of_1,4},
- {{try_case_end,{x,0}},180,ambiguous_catch_try_state}}] = Errors,
+ {{try_case_end,{x,0}},166,ambiguous_catch_try_state}}] = Errors,
ok.
undef_label(Config) when is_list(Config) ->
@@ -522,13 +525,8 @@ destroy_reg({Tag,N}) ->
bad_tuples(Config) ->
Errors = do_val(bad_tuples, Config),
[{{bad_tuples,heap_overflow,1},
- {{put,{x,0}},9,{heap_overflow,{left,0},{wanted,1}}}},
- {{bad_tuples,long,2},
- {{put,{atom,too_long}},9,not_building_a_tuple}},
- {{bad_tuples,self_referential,1},
- {{put,{x,1}},8,{unfinished_tuple,{x,1}}}},
- {{bad_tuples,short,1},
- {{move,{x,1},{x,0}},8,{unfinished_tuple,{x,1}}}}] = Errors,
+ {{put_tuple2,{x,0},{list,[{atom,ok},{x,0}]}},6,
+ {heap_overflow,{left,2},{wanted,3}}}}] = Errors,
ok.
@@ -555,7 +553,7 @@ receive_stacked(Config) ->
{{test_heap,3,0},11,{fragile_message_reference,{y,_}}}},
{{receive_stacked,f5,0},
{{loop_rec_end,{f,23}},
- 24,
+ 22,
{fragile_message_reference,{y,_}}}},
{{receive_stacked,f6,0},
{{gc_bif,byte_size,{f,29},0,[{y,_}],{x,0}},
@@ -575,7 +573,7 @@ receive_stacked(Config) ->
{fragile_message_reference,{y,_}}}},
{{receive_stacked,m2,0},
{{loop_rec_end,{f,48}},
- 34,
+ 32,
{fragile_message_reference,{y,_}}}}] = Errors,
%% Compile the original source code as a smoke test.
@@ -1039,6 +1037,25 @@ container_performance(Config) ->
_ -> ok
end.
+%% Type inference was half-broken for relational operators, being implemented
+%% for is_lt/is_ge instructions but not the {bif,RelOp} form.
+infer_relops(_Config) ->
+ [lt = infer_relops_1(N) || N <- lists:seq(0,3)],
+ [ge = infer_relops_1(N) || N <- lists:seq(4,7)],
+ ok.
+
+infer_relops_1(N) ->
+ true = N >= 0,
+ Below4 = N < 4,
+ id(N), %% Force Below4 to use the {bif,'<'} form instead of is_lt
+ case Below4 of
+ true -> infer_relops_true(Below4, N);
+ false -> infer_relops_false(Below4, N)
+ end.
+
+infer_relops_true(_, _) -> lt.
+infer_relops_false(_, _) -> ge.
+
%% OTP-18365: A brainfart in inference for '=/=' inverted the results.
not_equal_inference(_Config) ->
{'EXIT', {function_clause, _}} = (catch not_equal_inference_1(id([0]))),
@@ -1047,6 +1064,58 @@ not_equal_inference(_Config) ->
not_equal_inference_1(X) when (X /= []) /= is_port(0 div 0) ->
[X || _ <- []].
+bad_bin_unit(_Config) ->
+ {'EXIT', {function_clause,_}} = catch bad_bin_unit_1(<<1:1>>),
+ [] = bad_bin_unit_2(),
+ ok.
+
+bad_bin_unit_1(<<X:((ok > {<<(true andalso ok)>>}) orelse 1)>>) ->
+ try
+ bad_bin_unit_1_a()
+ after
+ -(X + bad_bin_unit_1_b(not ok)),
+ try
+ ok
+ catch
+ _ ->
+ ok;
+ _ ->
+ ok;
+ _ ->
+ ok;
+ _ ->
+ ok;
+ _ ->
+ ok;
+ _ ->
+ ok
+ end
+ end.
+
+bad_bin_unit_1_a() -> ok.
+bad_bin_unit_1_b(_) -> ok.
+
+bad_bin_unit_2() ->
+ [
+ ok
+ || <<X:(is_number(<<(<<(0 bxor 0)>>)>>) orelse 1)>> <= <<>>,
+ #{X := _} <- ok
+ ].
+
+%% GH-6962: Type inference with singleton types in registers was weaker than
+%% inference on their corresponding literals.
+singleton_inference(Config) ->
+ Mod = ?FUNCTION_NAME,
+
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "singleton_inference.erl"),
+
+ {ok, Mod} = compile:file(File, [no_copt, no_bool_opt, no_ssa_opt]),
+
+ ok = Mod:test(),
+
+ ok.
+
%% GH-6969: A type was made concrete even though that added no additional
%% information.
inert_update_type(_Config) ->
@@ -1060,5 +1129,22 @@ mike([Head | _Rest]) -> joe(Head).
joe({Name, 42}) -> Name;
joe({sys_period, {A, _B}}) -> {41, 42, A}.
+range_inference(_Config) ->
+ ok = range_inference_1(id(<<$a>>)),
+ ok = range_inference_1(id(<<0>>)),
+ ok = range_inference_1(id(<<1114111/utf8>>)),
+
+ ok.
+
+range_inference_1(<<X/utf8>>) ->
+ case 9223372036854775807 - abs(X) of
+ Y when X < Y ->
+ ok;
+ 9223372036854775807 ->
+ ok;
+ -2147483648 ->
+ ok
+ end.
+
id(I) ->
I.