diff options
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/Makefile | 15 | ||||
-rw-r--r-- | lib/compiler/test/beam_except_SUITE.erl | 41 | ||||
-rw-r--r-- | lib/compiler/test/beam_jump_SUITE.erl | 47 | ||||
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 16 | ||||
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 82 | ||||
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S | 4 | ||||
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S | 4 | ||||
-rw-r--r-- | lib/compiler/test/bif_SUITE.erl | 7 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 287 | ||||
-rw-r--r-- | lib/compiler/test/compiler.cover | 5 | ||||
-rw-r--r-- | lib/compiler/test/float_SUITE.erl | 23 | ||||
-rw-r--r-- | lib/compiler/test/inline_SUITE.erl | 30 | ||||
-rw-r--r-- | lib/compiler/test/inline_SUITE_data/barnes2.erl | 2 | ||||
-rw-r--r-- | lib/compiler/test/match_SUITE.erl | 15 | ||||
-rw-r--r-- | lib/compiler/test/misc_SUITE.erl | 12 | ||||
-rw-r--r-- | lib/compiler/test/receive_SUITE.erl | 30 | ||||
-rw-r--r-- | lib/compiler/test/test_lib.erl | 66 | ||||
-rw-r--r-- | lib/compiler/test/warnings_SUITE.erl | 33 |
18 files changed, 401 insertions, 318 deletions
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index f042a5cb51..db8eb7e2e1 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -107,6 +107,8 @@ CORE_MODULES = \ NO_MOD_OPT = $(NO_OPT) +NO_SSA_OPT = $(NO_OPT) + NO_OPT_MODULES= $(NO_OPT:%=%_no_opt_SUITE) NO_OPT_ERL_FILES= $(NO_OPT_MODULES:%=%.erl) POST_OPT_MODULES= $(NO_OPT:%=%_post_opt_SUITE) @@ -117,6 +119,8 @@ R21_MODULES= $(R21:%=%_r21_SUITE) R21_ERL_FILES= $(R21_MODULES:%=%.erl) NO_MOD_OPT_MODULES= $(NO_MOD_OPT:%=%_no_module_opt_SUITE) NO_MOD_OPT_ERL_FILES= $(NO_MOD_OPT_MODULES:%=%.erl) +NO_SSA_OPT_MODULES= $(NO_SSA_OPT:%=%_no_ssa_opt_SUITE) +NO_SSA_OPT_ERL_FILES= $(NO_SSA_OPT_MODULES:%=%.erl) ERL_FILES= $(MODULES:%=%.erl) CORE_FILES= $(CORE_MODULES:%=%.core) @@ -145,13 +149,16 @@ EBIN = . # Targets # ---------------------------------------------------- -make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \ +make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES) \ $(INLINE_ERL_FILES) $(R21_ERL_FILES) $(NO_MOD_OPT_ERL_FILES) $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ > $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt \ +no_ssa_opt +no_recv_opt $(ERL_COMPILE_FLAGS) \ -o$(EBIN) $(NO_OPT_MODULES) >> $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +no_share_opt +no_bsm_opt +no_fun_opt \ + +no_ssa_opt +no_recv_opt $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(NO_SSA_OPT_MODULES) >> $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +no_copt $(ERL_COMPILE_FLAGS) \ -o$(EBIN) $(POST_OPT_MODULES) >> $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +inline $(ERL_COMPILE_FLAGS) \ @@ -180,6 +187,9 @@ docs: %_no_opt_SUITE.erl: %_SUITE.erl sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ +%_no_ssa_opt_SUITE.erl: %_SUITE.erl + sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ + %_post_opt_SUITE.erl: %_SUITE.erl sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ @@ -205,7 +215,8 @@ release_tests_spec: make_emakefile $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)" $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \ $(INLINE_ERL_FILES) $(R21_ERL_FILES) \ - $(NO_MOD_OPT_ERL_FILES) "$(RELSYSDIR)" + $(NO_MOD_OPT_ERL_FILES) \ + $(NO_SSA_OPT_ERL_FILES) "$(RELSYSDIR)" $(INSTALL_DATA) $(CORE_FILES) "$(RELSYSDIR)" for file in $(ERL_DUMMY_FILES); do \ module=`basename $$file .erl`; \ diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl index da61931136..8e3b373d29 100644 --- a/lib/compiler/test/beam_except_SUITE.erl +++ b/lib/compiler/test/beam_except_SUITE.erl @@ -21,7 +21,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - multiple_allocs/1,coverage/1]). + multiple_allocs/1,bs_get_tail/1,coverage/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -31,6 +31,7 @@ all() -> groups() -> [{p,[parallel], [multiple_allocs, + bs_get_tail, coverage]}]. init_per_suite(Config) -> @@ -63,6 +64,17 @@ place(lee) -> conditions() -> (talking = going) = storage + [large = wanted]. +bs_get_tail(Config) -> + {<<"abc">>,0,0,Config} = bs_get_tail_1(id(<<0:32, "abc">>), 0, 0, Config), + {'EXIT', + {function_clause, + [{?MODULE,bs_get_tail_1,[<<>>,0,0,Config],_}|_]}} = + (catch bs_get_tail_1(id(<<>>), 0, 0, Config)), + ok. + +bs_get_tail_1(<<_:32, Rest/binary>>, Z1, Z2, F1) -> + {Rest,Z1,Z2,F1}. + coverage(_) -> File = {file,"fake.erl"}, ok = fc(a), @@ -72,9 +84,16 @@ coverage(_) -> {'EXIT',{function_clause, [{?MODULE,fc,[y],[File,{line,2}]}|_]}} = (catch fc(y)), - {'EXIT',{function_clause, - [{?MODULE,fc,[[a,b,c]],[File,{line,6}]}|_]}} = - (catch fc([a,b,c])), + case ?MODULE of + beam_except_no_opt_SUITE -> + %% There will be a different stack fram in + %% unoptimized code. + ok; + _ -> + {'EXIT',{function_clause, + [{?MODULE,fc,[[a,b,c]],[File,{line,6}]}|_]}} = + (catch fc([a,b,c])) + end, {'EXIT',{undef,[{erlang,error,[a,b,c],_}|_]}} = (catch erlang:error(a, b, c)), @@ -88,8 +107,19 @@ coverage(_) -> {'EXIT',{{strange,Self},[{?MODULE,foo,[any],[File,{line,14}]}|_]}} = (catch foo(any)), + {ok,succeed,1,2} = foobar(succeed, 1, 2), + {'EXIT',{function_clause,[{?MODULE,foobar,[[fail],1,2], + [{file,"fake.erl"},{line,16}]}|_]}} = + (catch foobar([fail], 1, 2)), + {'EXIT',{function_clause,[{?MODULE,fake_function_clause,[{a,b},42.0],_}|_]}} = + (catch fake_function_clause({a,b})), + ok. +fake_function_clause(A) -> error(function_clause, [A,42.0]). + +id(I) -> I. + -file("fake.erl", 1). fc(a) -> %Line 2 ok; %Line 3 @@ -104,3 +134,6 @@ bar(X) -> %Line 8 %% Cover collection code for function_clause exceptions. foo(A) -> %Line 13 error({strange,self()}, [A]). %Line 14 +%% Cover beam_except:tag_literal/1. +foobar(A, B, C) when is_atom(A) -> %Line 16 + {ok,A,B,C}. %Line 17 diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl index 759d884dc4..a456f31d79 100644 --- a/lib/compiler/test/beam_jump_SUITE.erl +++ b/lib/compiler/test/beam_jump_SUITE.erl @@ -79,12 +79,13 @@ checks(Wanted) -> {catch case river() of sheet -> begin +Wanted, if "da" -> Wanted end end end, catch case river() of sheet -> begin + Wanted, if "da" -> Wanted end end end}. unsafe_move_elimination(_Config) -> - {{left,right,false},false} = unsafe_move_elimination(left, right, false), - {{false,right,false},false} = unsafe_move_elimination(false, right, true), - {{true,right,right},right} = unsafe_move_elimination(true, right, true), + {{left,right,false},false} = unsafe_move_elimination_1(left, right, false), + {{false,right,false},false} = unsafe_move_elimination_1(false, right, true), + {{true,right,right},right} = unsafe_move_elimination_1(true, right, true), + [ok = unsafe_move_elimination_2(I) || I <- lists:seq(0,16)], ok. -unsafe_move_elimination(Left, Right, Simple0) -> +unsafe_move_elimination_1(Left, Right, Simple0) -> id(1), %% The move at label 29 would be removed by beam_jump, which is unsafe because @@ -115,6 +116,44 @@ unsafe_move_elimination(Left, Right, Simple0) -> end, {id({Left,Right,Simple}),Simple}. +unsafe_move_elimination_2(Int) -> + %% The type optimization pass would recognize that TagInt can only be + %% [0 .. 7], so the first 'case' would select_val over [0 .. 6] and swap + %% out the fail label with the block for 7. + %% + %% A later optimization would merge this block with 'expects_h' in the + %% second case, as the latter is only reachable from the former. + %% + %% ... but this broke down when the move elimination optimization didn't + %% take the fail label of the first select_val into account. This caused it + %% to believe that the only way to reach 'expects_h' was through the second + %% case when 'Tag' =:= 'h', which made it remove the move instruction + %% added in the first case, passing garbage to expects_h/2. + TagInt = Int band 2#111, + Tag = case TagInt of + 0 -> a; + 1 -> b; + 2 -> c; + 3 -> d; + 4 -> e; + 5 -> f; + 6 -> g; + 7 -> h + end, + case Tag of + g -> expects_g(TagInt, Tag); + h -> expects_h(TagInt, Tag); + _ -> Tag = id(Tag), ok + end. + +expects_g(6, Atom) -> + Atom = id(g), + ok. + +expects_h(7, Atom) -> + Atom = id(h), + ok. + -record(message2, {id, p1}). -record(message3, {id, p1, p2}). diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 6efa98de44..a7ffc3f60a 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -222,6 +222,9 @@ coverage(Config) -> booleans(_Config) -> {'EXIT',{{case_clause,_},_}} = (catch do_booleans_1(42)), + ok = do_booleans_2(42, 41), + error = do_booleans_2(42, 42), + AnyAtom = id(atom), true = is_atom(AnyAtom), false = is_boolean(AnyAtom), @@ -250,6 +253,19 @@ do_booleans_1(B) -> no -> no end. +do_booleans_2(A, B) -> + Not = not do_booleans_cmp(A, B), + case Not of + true -> + case Not of + true -> error; + false -> ok + end; + false -> ok + end. + +do_booleans_cmp(A, B) -> A > B. + setelement(_Config) -> T0 = id({a,42}), {a,_} = T0, diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 585d0e7191..8b39fce479 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -34,7 +34,7 @@ undef_label/1,illegal_instruction/1,failing_gc_guard_bif/1, map_field_lists/1,cover_bin_opt/1, val_dsetel/1,bad_tuples/1,bad_try_catch_nesting/1, - receive_stacked/1,aliased_types/1]). + receive_stacked/1,aliased_types/1,type_conflict/1]). -include_lib("common_test/include/ct.hrl"). @@ -63,7 +63,7 @@ groups() -> undef_label,illegal_instruction,failing_gc_guard_bif, map_field_lists,cover_bin_opt,val_dsetel, bad_tuples,bad_try_catch_nesting, - receive_stacked,aliased_types]}]. + receive_stacked,aliased_types,type_conflict]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), @@ -107,13 +107,12 @@ xrange(Config) when is_list(Config) -> Errors = do_val(xrange, Config), [{{t,sum_1,2}, {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4, - {uninitialized_reg,{x,-1}}}}, + {bad_register,{x,-1}}}}, {{t,sum_2,2}, - {{bif,'+',{f,0},[{x,0},{x,1023}],{x,0}},4, - {uninitialized_reg,{x,1023}}}}, + {{bif,'+',{f,0},[{x,0},{x,1023}],{x,0}},4,limit}}, {{t,sum_3,2}, {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4, - {invalid_store,{x,-1},number}}}, + {bad_register,{x,-1}}}}, {{t,sum_4,2}, {{bif,'+',{f,0},[{x,0},{x,1}],{x,1023}},4,limit}}] = Errors, ok. @@ -122,15 +121,15 @@ yrange(Config) when is_list(Config) -> Errors = do_val(yrange, Config), [{{t,sum_1,2}, {{move,{x,1},{y,-1}},5, - {invalid_store,{y,-1},term}}}, + {bad_register,{y,-1}}}}, {{t,sum_2,2}, {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},7, - {uninitialized_reg,{y,1024}}}}, + limit}}, {{t,sum_3,2}, {{move,{x,1},{y,1024}},5,limit}}, {{t,sum_4,2}, {{move,{x,1},{y,-1}},5, - {invalid_store,{y,-1},term}}}] = Errors, + {bad_register,{y,-1}}}}] = Errors, ok. stack(Config) when is_list(Config) -> @@ -157,9 +156,9 @@ call_last(Config) when is_list(Config) -> merge_undefined(Config) when is_list(Config) -> Errors = do_val(merge_undefined, Config), [{{t,handle_call,2}, - {{call_ext,1,{extfunc,erlang,exit,1}}, - 10, - {uninitialized_reg,{y,0}}}}] = Errors, + {{call_ext,2,{extfunc,debug,filter,2}}, + 22, + {uninitialized_reg,{y,_}}}}] = Errors, ok. uninit(Config) when is_list(Config) -> @@ -178,7 +177,7 @@ unsafe_catch(Config) when is_list(Config) -> Errors = do_val(unsafe_catch, Config), [{{t,small,2}, {{bs_put_integer,{f,0},{integer,16},1, - {field_flags,[unsigned,big]},{y,0}}, + {field_flags,[unsigned,big]},{y,0}}, 20, {unassigned,{y,0}}}}] = Errors, ok. @@ -211,19 +210,19 @@ bad_catch_try(Config) when is_list(Config) -> Errors = do_val(bad_catch_try, Config), [{{bad_catch_try,bad_1,1}, {{'catch',{x,0},{f,3}}, - 5,{invalid_store,{x,0},{catchtag,[3]}}}}, + 5,{invalid_tag_register,{x,0}}}}, {{bad_catch_try,bad_2,1}, {{catch_end,{x,9}}, - 8,{source_not_y_reg,{x,9}}}}, + 8,{invalid_tag_register,{x,9}}}}, {{bad_catch_try,bad_3,1}, - {{catch_end,{y,1}},9,{bad_type,{atom,kalle}}}}, + {{catch_end,{y,1}},9,{invalid_tag,{y,1},{atom,kalle}}}}, {{bad_catch_try,bad_4,1}, - {{'try',{x,0},{f,15}},5,{invalid_store,{x,0},{trytag,[15]}}}}, + {{'try',{x,0},{f,15}},5,{invalid_tag_register,{x,0}}}}, {{bad_catch_try,bad_5,1}, - {{try_case,{y,1}},12,{bad_type,term}}}, + {{try_case,{y,1}},12,{invalid_tag,{y,1},term}}}, {{bad_catch_try,bad_6,1}, {{move,{integer,1},{y,1}},7, - {invalid_store,{y,1},{integer,1}}}}] = Errors, + {invalid_store,{y,1}}}}] = Errors, ok. cons_guard(Config) when is_list(Config) -> @@ -247,7 +246,7 @@ freg_range(Config) when is_list(Config) -> {{t,sum_3,2}, {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}}, 7, - {bad_target,{fr,-1}}}}, + {bad_register,{fr,-1}}}}, {{t,sum_4,2}, {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}}, 7, @@ -539,37 +538,37 @@ receive_stacked(Config) -> [{{receive_stacked,f1,0}, {{loop_rec_end,{f,3}}, 17, - {fragile_message_reference,{y,0}}}}, + {fragile_message_reference,{y,_}}}}, {{receive_stacked,f2,0}, - {{test_heap,3,0},10,{fragile_message_reference,{y,1}}}}, + {{test_heap,3,0},10,{fragile_message_reference,{y,_}}}}, {{receive_stacked,f3,0}, - {{test_heap,3,0},10,{fragile_message_reference,{y,1}}}}, + {{test_heap,3,0},10,{fragile_message_reference,{y,_}}}}, {{receive_stacked,f4,0}, - {{test_heap,3,0},10,{fragile_message_reference,{y,1}}}}, + {{test_heap,3,0},10,{fragile_message_reference,{y,_}}}}, {{receive_stacked,f5,0}, {{loop_rec_end,{f,23}}, 23, - {fragile_message_reference,{y,1}}}}, + {fragile_message_reference,{y,_}}}}, {{receive_stacked,f6,0}, - {{gc_bif,byte_size,{f,29},0,[{y,0}],{x,0}}, + {{gc_bif,byte_size,{f,29},0,[{y,_}],{x,0}}, 12, - {fragile_message_reference,{y,0}}}}, + {fragile_message_reference,{y,_}}}}, {{receive_stacked,f7,0}, {{loop_rec_end,{f,33}}, 20, - {fragile_message_reference,{y,0}}}}, + {fragile_message_reference,{y,_}}}}, {{receive_stacked,f8,0}, {{loop_rec_end,{f,38}}, 20, - {fragile_message_reference,{y,0}}}}, + {fragile_message_reference,{y,_}}}}, {{receive_stacked,m1,0}, {{loop_rec_end,{f,43}}, 19, - {fragile_message_reference,{y,0}}}}, + {fragile_message_reference,{y,_}}}}, {{receive_stacked,m2,0}, {{loop_rec_end,{f,48}}, 33, - {fragile_message_reference,{y,0}}}}] = Errors, + {fragile_message_reference,{y,_}}}}] = Errors, %% Compile the original source code as a smoke test. Data = proplists:get_value(data_dir, Config), @@ -631,6 +630,27 @@ aliased_types_3(Bug) -> hd(List) end. + +%% ERL-867; validation proceeded after a type conflict, causing incorrect types +%% to be joined. + +-record(r, { e1 = e1, e2 = e2 }). + +type_conflict(Config) when is_list(Config) -> + {e1, e2} = type_conflict_1(#r{}), + ok. + +type_conflict_1(C) -> + Src = id(C#r.e2), + TRes = try id(Src) of + R -> R + catch + %% C:R can never match, yet it assumed that the type of 'C' was + %% an atom from here on. + C:R -> R + end, + {C#r.e1, TRes}. + %%%------------------------------------------------------------------------- transform_remove(Remove, Module) -> diff --git a/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S b/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S index 481d55045d..aa344807e4 100644 --- a/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S +++ b/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S @@ -15,8 +15,9 @@ {select_val,{x,0},{f,1},{list,[{atom,gurka},{f,3},{atom,delete},{f,4}]}}. {label,3}. {allocate_heap,2,6,2}. - %% The Y registers are not initialized here. {test,is_eq_exact,{f,5},[{x,0},{atom,ok}]}. + %% This is unreachable since {x,0} is known not to be 'ok'. We should not + %% fail with "uninitialized y registers" on erlang:exit/1 {move,{atom,nisse},{x,0}}. {call_ext,1,{extfunc,erlang,exit,1}}. {label,4}. @@ -29,6 +30,7 @@ {call_ext,2,{extfunc,io,format,2}}. {test,is_ne_exact,{f,6},[{x,0},{atom,ok}]}. {label,5}. + %% The Y registers are not initialized here. {move,{atom,logReader},{x,1}}. {move,{atom,console},{x,0}}. {call_ext,2,{extfunc,debug,filter,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S b/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S index 5b974119c6..a878204d16 100644 --- a/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S +++ b/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S @@ -240,7 +240,7 @@ {y,0}}. {'%',{no_bin_opt,{binary_used_in,{test,is_binary,{f,34},[{y,0}]}}, [63,{file,"receive_stacked.erl"}]}}. - {test,is_binary,{f,34},[{y,0}]}. + {test,is_eq_exact,{f,34},[{y,0},{literal,<<0,1,2,3>>}]}. remove_message. {move,{integer,42},{x,0}}. {line,[{location,"receive_stacked.erl",64}]}. @@ -283,7 +283,7 @@ {y,0}}. {'%',{no_bin_opt,{[{x,1},{y,0}],{loop_rec_end,{f,38}},not_handled}, [70,{file,"receive_stacked.erl"}]}}. - {test,is_binary,{f,39},[{x,0}]}. + {test,is_eq_exact,{f,39},[{x,0},{literal,<<0,1,2,3>>}]}. remove_message. {move,{integer,42},{x,0}}. {line,[{location,"receive_stacked.erl",71}]}. diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl index 42ba5d5365..423a7666af 100644 --- a/lib/compiler/test/bif_SUITE.erl +++ b/lib/compiler/test/bif_SUITE.erl @@ -23,7 +23,7 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, - beam_validator/1,trunc_and_friends/1,cover_safe_bifs/1]). + beam_validator/1,trunc_and_friends/1,cover_safe_and_pure_bifs/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -35,7 +35,7 @@ groups() -> [{p,[parallel], [beam_validator, trunc_and_friends, - cover_safe_bifs + cover_safe_and_pure_bifs ]}]. init_per_suite(Config) -> @@ -106,7 +106,7 @@ trunc_template(Func, Bif) -> catch error:badarg -> ok end, ok."). -cover_safe_bifs(Config) -> +cover_safe_and_pure_bifs(Config) -> _ = get(), _ = get_keys(a), _ = group_leader(), @@ -118,5 +118,6 @@ cover_safe_bifs(Config) -> _ = processes(), _ = registered(), _ = term_to_binary(Config), + 42 = list_to_integer("2A", 16), ok. diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 7452466666..408af80dd9 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -28,12 +28,12 @@ init_per_group/2,end_per_group/2, app_test/1,appup_test/1, debug_info/4, custom_debug_info/1, custom_compile_info/1, - file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1, + file_1/1, forms_2/1, module_mismatch/1, outdir/1, binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, other_output/1, kernel_listing/1, encrypted_abstr/1, strict_record/1, utf8_atoms/1, utf8_functions/1, extra_chunks/1, cover/1, env/1, core_pp/1, tuple_calls/1, - core_roundtrip/1, asm/1, optimized_guards/1, + core_roundtrip/1, asm/1, sys_pre_attributes/1, dialyzer/1, warnings/1, pre_load_check/1, env_compiler_options/1, bc_options/1, deterministic_include/1, deterministic_paths/1 @@ -46,11 +46,11 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -spec all() -> all_return_type(). all() -> - [app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir, + [app_test, appup_test, file_1, forms_2, module_mismatch, outdir, binary, makedep, cond_and_ifdef, listings, listings_big, other_output, kernel_listing, encrypted_abstr, tuple_calls, strict_record, utf8_atoms, utf8_functions, extra_chunks, - cover, env, core_pp, core_roundtrip, asm, optimized_guards, + cover, env, core_pp, core_roundtrip, asm, sys_pre_attributes, dialyzer, warnings, pre_load_check, env_compiler_options, custom_debug_info, bc_options, custom_compile_info, deterministic_include, deterministic_paths]. @@ -104,6 +104,7 @@ file_1(Config) when is_list(Config) -> compile_and_verify(Simple, Target, []), compile_and_verify(Simple, Target, [native]), compile_and_verify(Simple, Target, [debug_info]), + compile_and_verify(Simple, Target, [no_postopt]), {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage {ok,simple} = compile:file(Simple, [{eprof,beam_z}]), %Coverage @@ -231,17 +232,6 @@ module_mismatch(Config) when is_list(Config) -> ok. -big_file(Config) when is_list(Config) -> - {Big,Target} = get_files(Config, big, "big_file"), - ok = file:set_cwd(filename:dirname(Target)), - compile_and_verify(Big, Target, []), - compile_and_verify(Big, Target, [debug_info]), - compile_and_verify(Big, Target, [no_postopt]), - - %% Cleanup. - ok = file:delete(Target), - ok. - %% Tests that the {outdir, Dir} option works. outdir(Config) when is_list(Config) -> @@ -370,42 +360,37 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> TargetDir = filename:join(PrivDir, listings), ok = file:make_dir(TargetDir), - %% Test all dedicated listing options. - do_listing(Simple, TargetDir, 'S'), - do_listing(Simple, TargetDir, 'E'), - do_listing(Simple, TargetDir, 'P'), - do_listing(Simple, TargetDir, dpp, ".pp"), - do_listing(Simple, TargetDir, dabstr, ".abstr"), - do_listing(Simple, TargetDir, dexp, ".expand"), - do_listing(Simple, TargetDir, dcore, ".core"), - do_listing(Simple, TargetDir, doldinline, ".oldinline"), - do_listing(Simple, TargetDir, dinline, ".inline"), - do_listing(Simple, TargetDir, dcore, ".core"), - do_listing(Simple, TargetDir, dcopt, ".copt"), - do_listing(Simple, TargetDir, dcbsm, ".core_bsm"), - do_listing(Simple, TargetDir, dsetel, ".dsetel"), - do_listing(Simple, TargetDir, dkern, ".kernel"), - do_listing(Simple, TargetDir, dssa, ".ssa"), - do_listing(Simple, TargetDir, dssaopt, ".ssaopt"), - do_listing(Simple, TargetDir, dprecg, ".precodegen"), - do_listing(Simple, TargetDir, dcg, ".codegen"), - do_listing(Simple, TargetDir, dblk, ".block"), - do_listing(Simple, TargetDir, dexcept, ".except"), - do_listing(Simple, TargetDir, djmp, ".jump"), - do_listing(Simple, TargetDir, dclean, ".clean"), - do_listing(Simple, TargetDir, dpeep, ".peep"), - do_listing(Simple, TargetDir, dopt, ".optimize"), - do_listing(Simple, TargetDir, diffable, ".S"), - - %% First clean up. - Listings = filename:join(PrivDir, listings), - lists:foreach(fun(F) -> ok = file:delete(F) end, - filelib:wildcard(filename:join(Listings, "*"))), + List = [{'S',".S"}, + {'E',".E"}, + {'P',".P"}, + {dpp, ".pp"}, + {dabstr, ".abstr"}, + {dexp, ".expand"}, + {dcore, ".core"}, + {doldinline, ".oldinline"}, + {dinline, ".inline"}, + {dcore, ".core"}, + {dcopt, ".copt"}, + {dcbsm, ".core_bsm"}, + {dkern, ".kernel"}, + {dssa, ".ssa"}, + {dssaopt, ".ssaopt"}, + {dprecg, ".precodegen"}, + {dcg, ".codegen"}, + {dblk, ".block"}, + {dexcept, ".except"}, + {djmp, ".jump"}, + {dclean, ".clean"}, + {dpeep, ".peep"}, + {dopt, ".optimize"}, + {diffable, ".S"}], + p_listings(List, Simple, TargetDir), %% Test options that produce a listing file if 'binary' is not given. do_listing(Simple, TargetDir, to_pp, ".P"), do_listing(Simple, TargetDir, to_exp, ".E"), do_listing(Simple, TargetDir, to_core0, ".core"), + Listings = filename:join(PrivDir, listings), ok = file:delete(filename:join(Listings, File ++ ".core")), do_listing(Simple, TargetDir, to_core, ".core"), do_listing(Simple, TargetDir, to_kernel, ".kernel"), @@ -421,24 +406,35 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> listings_big(Config) when is_list(Config) -> {Big,Target} = get_files(Config, big, listings_big), TargetDir = filename:dirname(Target), - do_listing(Big, TargetDir, 'S'), - do_listing(Big, TargetDir, 'E'), - do_listing(Big, TargetDir, 'P'), - do_listing(Big, TargetDir, dkern, ".kernel"), - do_listing(Big, TargetDir, dssa, ".ssa"), - do_listing(Big, TargetDir, dssaopt, ".ssaopt"), - do_listing(Big, TargetDir, dprecg, ".precodegen"), - do_listing(Big, TargetDir, to_dis, ".dis"), - - TargetNoext = filename:rootname(Target, code:objfile_extension()), - {ok,big} = compile:file(TargetNoext, [from_asm,{outdir,TargetDir}]), - - %% Cleanup. - ok = file:delete(Target), - lists:foreach(fun(F) -> ok = file:delete(F) end, - filelib:wildcard(filename:join(TargetDir, "*"))), - ok = file:del_dir(TargetDir), - ok. + List = [{'S',".S"}, + {'E',".E"}, + {'P',".P"}, + {dkern, ".kernel"}, + {dssa, ".ssa"}, + {dssaopt, ".ssaopt"}, + {dprecg, ".precodegen"}, + {to_dis, ".dis"}], + p_listings(List, Big, TargetDir). + +p_listings(List, File, BaseDir) -> + Run = fun({Option,Extension}) -> + Uniq = erlang:unique_integer([positive]), + Dir = filename:join(BaseDir, integer_to_list(Uniq)), + ok = file:make_dir(Dir), + try + do_listing(File, Dir, Option, Extension), + ok + catch + Class:Error:Stk -> + io:format("~p:~p\n~p\n", [Class,Error,Stk]), + error + after + _ = [ok = file:delete(F) || + F <- filelib:wildcard(filename:join(Dir, "*"))], + ok = file:del_dir(Dir) + end + end, + test_lib:p_run(Run, List). other_output(Config) when is_list(Config) -> {Simple,_Target} = get_files(Config, simple, "other_output"), @@ -685,9 +681,6 @@ cover(Config) when is_list(Config) -> io:format("~p\n", [compile:options()]), ok. -do_listing(Source, TargetDir, Type) -> - do_listing(Source, TargetDir, Type, "." ++ atom_to_list(Type)). - do_listing(Source, TargetDir, Type, Ext) -> io:format("Source: ~p TargetDir: ~p\n Type: ~p Ext: ~p\n", [Source, TargetDir, Type, Ext]), @@ -1174,85 +1167,6 @@ do_asm(Beam, Outdir) -> error end. -%% Make sure that guards are fully optimized. Guards should -%% should use 'test' instructions, not 'bif' instructions. - -optimized_guards(_Config) -> - TestBeams = get_unique_beam_files(), - test_lib:p_run(fun(F) -> do_opt_guards(F) end, TestBeams). - -do_opt_guards(Beam) -> - {ok,{M,[{abstract_code,{raw_abstract_v1,A}}]}} = - beam_lib:chunks(Beam, [abstract_code]), - try - {ok,M,Asm} = compile:forms(A, ['S']), - do_opt_guards_mod(Asm) - catch Class:Error:Stk -> - io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]), - error - end. - -do_opt_guards_mod({Mod,_Exp,_Attr,Asm,_NumLabels}) -> - case do_opt_guards_fs(Mod, Asm) of - [] -> - ok; - [_|_]=Bifs -> - io:format("ERRORS FOR ~p:\n~p\n", [Mod,Bifs]), - error - end. - -do_opt_guards_fs(Mod, [{function,Name,Arity,_,Is}|Fs]) -> - Bifs0 = do_opt_guards_fun(Is), - - %% The compiler does not attempt to optimize 'xor'. - %% Therefore, ignore all functions that use 'xor' in - %% a guard. - Bifs = case lists:any(fun({bif,'xor',_,_,_}) -> true; - (_) -> false - end, Bifs0) of - true -> []; - false -> Bifs0 - end, - - %% Filter out the allowed exceptions. - FA = {Name,Arity}, - case {Bifs,is_exception(Mod, FA)} of - {[_|_],true} -> - io:format("~p:~p/~p IGNORED:\n~p\n", - [Mod,Name,Arity,Bifs]), - do_opt_guards_fs(Mod, Fs); - {[_|_],false} -> - [{FA,Bifs}|do_opt_guards_fs(Mod, Fs)]; - {[],false} -> - do_opt_guards_fs(Mod, Fs); - {[],true} -> - io:format("Redundant exception for ~p:~p/~p\n", - [Mod,Name,Arity]), - error(redundant) - end; -do_opt_guards_fs(_, []) -> []. - -do_opt_guards_fun([{bif,Name,{f,F},As,_}=I|Is]) when F =/= 0 -> - Arity = length(As), - case erl_internal:comp_op(Name, Arity) orelse - erl_internal:bool_op(Name, Arity) orelse - erl_internal:new_type_test(Name, Arity) of - true -> - [I|do_opt_guards_fun(Is)]; - false -> - do_opt_guards_fun(Is) - end; -do_opt_guards_fun([_|Is]) -> - do_opt_guards_fun(Is); -do_opt_guards_fun([]) -> []. - -is_exception(guard_SUITE, {'-complex_not/1-fun-4-',1}) -> true; -is_exception(guard_SUITE, {'-complex_not/1-fun-5-',1}) -> true; -is_exception(guard_SUITE, {bad_guards,1}) -> true; -is_exception(guard_SUITE, {nested_not_2b,6}) -> true; %% w/o type optimization -is_exception(guard_SUITE, {nested_not_2b,2}) -> true; %% with type optimization -is_exception(_, _) -> false. - sys_pre_attributes(Config) -> DataDir = proplists:get_value(data_dir, Config), File = filename:join(DataDir, "attributes.erl"), @@ -1469,44 +1383,49 @@ env_compiler_options(_Config) -> bc_options(Config) -> DataDir = proplists:get_value(data_dir, Config), - 101 = highest_opcode(DataDir, small_float, [no_get_hd_tl,no_line_info]), - - 103 = highest_opcode(DataDir, big, - [no_put_tuple2, - no_get_hd_tl,no_ssa_opt_record, - no_line_info,no_stack_trimming]), - - 125 = highest_opcode(DataDir, small_float, - [no_get_hd_tl,no_line_info,no_ssa_opt_float]), - - 132 = highest_opcode(DataDir, small, - [no_put_tuple2,no_get_hd_tl,no_ssa_opt_record, - no_ssa_opt_float,no_line_info,no_bsm3]), - - 153 = highest_opcode(DataDir, small, [r20]), - 153 = highest_opcode(DataDir, small, [r21]), - - 136 = highest_opcode(DataDir, big, [no_put_tuple2,no_get_hd_tl, - no_ssa_opt_record,no_line_info]), - - 153 = highest_opcode(DataDir, big, [no_put_tuple2,no_get_hd_tl, - no_ssa_opt_record]), - 153 = highest_opcode(DataDir, big, [r16]), - 153 = highest_opcode(DataDir, big, [r17]), - 153 = highest_opcode(DataDir, big, [r18]), - 153 = highest_opcode(DataDir, big, [r19]), - 153 = highest_opcode(DataDir, small_float, [r16]), - 153 = highest_opcode(DataDir, small_float, []), - - 158 = highest_opcode(DataDir, small_maps, [r17]), - 158 = highest_opcode(DataDir, small_maps, [r18]), - 158 = highest_opcode(DataDir, small_maps, [r19]), - 158 = highest_opcode(DataDir, small_maps, [r20]), - 158 = highest_opcode(DataDir, small_maps, [r21]), - - 164 = highest_opcode(DataDir, small_maps, []), - 164 = highest_opcode(DataDir, big, []), - + L = [{101, small_float, [no_get_hd_tl,no_line_info]}, + {103, big, [no_put_tuple2,no_get_hd_tl,no_ssa_opt_record, + no_line_info,no_stack_trimming]}, + {125, small_float, [no_get_hd_tl,no_line_info,no_ssa_opt_float]}, + + {132, small, [no_put_tuple2,no_get_hd_tl,no_ssa_opt_record, + no_ssa_opt_float,no_line_info,no_bsm3]}, + + {153, small, [r20]}, + {153, small, [r21]}, + + {136, big, [no_put_tuple2,no_get_hd_tl, + no_ssa_opt_record,no_line_info]}, + + {153, big, [no_put_tuple2,no_get_hd_tl, no_ssa_opt_record]}, + {153, big, [r16]}, + {153, big, [r17]}, + {153, big, [r18]}, + {153, big, [r19]}, + {153, small_float, [r16]}, + {153, small_float, []}, + + {158, small_maps, [r17]}, + {158, small_maps, [r18]}, + {158, small_maps, [r19]}, + {158, small_maps, [r20]}, + {158, small_maps, [r21]}, + + {164, small_maps, []}, + {164, big, []} + ], + + Test = fun({Expected,Mod,Options}) -> + case highest_opcode(DataDir, Mod, Options) of + Expected -> + ok; + Got -> + io:format("*** module ~p, options ~p => got ~p; expected ~p\n", + [Mod,Options,Got,Expected]), + error + end + end, + test_lib:p_run(Test, L), ok. highest_opcode(DataDir, Mod, Opt) -> diff --git a/lib/compiler/test/compiler.cover b/lib/compiler/test/compiler.cover index 3fd7fc1937..fac0f9947c 100644 --- a/lib/compiler/test/compiler.cover +++ b/lib/compiler/test/compiler.cover @@ -1,5 +1,4 @@ -{incl_app,compiler,details}. - %% -*- erlang -*- +{local_only,compiler,true}. +{incl_app,compiler,details}. {excl_mods,compiler,[core_scan,core_parse]}. - diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl index 831e8279aa..0fa8070dc8 100644 --- a/lib/compiler/test/float_SUITE.erl +++ b/lib/compiler/test/float_SUITE.erl @@ -21,15 +21,16 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, pending/1,bif_calls/1,math_functions/1,mixed_float_and_int/1, - subtract_number_type/1]). + subtract_number_type/1,float_followed_by_guard/1]). -include_lib("common_test/include/ct.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [pending, bif_calls, math_functions, - mixed_float_and_int, subtract_number_type]. + mixed_float_and_int, subtract_number_type, + float_followed_by_guard]. groups() -> []. @@ -187,5 +188,21 @@ fact(0, P) -> P; fact(1, P) -> P; fact(N, P) -> fact(N-1, P*N). +float_followed_by_guard(Config) when is_list(Config) -> + true = ffbg_1(5, 1), + false = ffbg_1(1, 5), + ok. + +ffbg_1(A, B0) -> + %% This is a non-guard block followed by a *guard block* that starts with a + %% floating point operation, and the compiler erroneously assumed that it + %% was safe to skip fcheckerror because the next block started with a float + %% op. + B = id(B0) / 1.0, + if + A - B > 0.0 -> true; + A - B =< 0.0 -> false + end. + id(I) -> I. diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl index 69c9dcba69..aff1a56c47 100644 --- a/lib/compiler/test/inline_SUITE.erl +++ b/lib/compiler/test/inline_SUITE.erl @@ -42,13 +42,9 @@ groups() -> init_per_suite(Config) -> test_lib:recompile(?MODULE), - Pa = "-pa " ++ filename:dirname(code:which(?MODULE)), - {ok,Node} = start_node(compiler, Pa), - [{testing_node,Node}|Config]. + Config. -end_per_suite(Config) -> - Node = proplists:get_value(testing_node, Config), - test_server:stop_node(Node), +end_per_suite(_Config) -> ok. init_per_group(_GroupName, Config) -> @@ -89,7 +85,6 @@ attribute(Config) when is_list(Config) -> ?comp(maps_inline_test). try_inline(Mod, Config) -> - Node = proplists:get_value(testing_node, Config), Src = filename:join(proplists:get_value(data_dir, Config), atom_to_list(Mod)), Out = proplists:get_value(priv_dir,Config), @@ -100,7 +95,7 @@ try_inline(Mod, Config) -> bin_opt_info,clint,ssalint]), ct:timetrap({minutes,10}), - NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), + NormalResult = load_and_call(Out, Mod), %% Inlining. io:format("Compiling with old inliner: ~s\n", [Src]), @@ -109,7 +104,7 @@ try_inline(Mod, Config) -> %% Run inlined code. ct:timetrap({minutes,10}), - OldInlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), + OldInlinedResult = load_and_call(Out, Mod), %% Compare results. compare(NormalResult, OldInlinedResult), @@ -122,7 +117,7 @@ try_inline(Mod, Config) -> %% Run inlined code. ct:timetrap({minutes,10}), - InlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), + InlinedResult = load_and_call(Out, Mod), %% Compare results. compare(NormalResult, InlinedResult), @@ -131,6 +126,11 @@ try_inline(Mod, Config) -> %% Delete Beam file. ok = file:delete(filename:join(Out, atom_to_list(Mod)++code:objfile_extension())), + %% Delete loaded module. + _ = code:purge(Mod), + _ = code:delete(Mod), + _ = code:purge(Mod), + ok. compare(Same, Same) -> ok; @@ -144,12 +144,6 @@ compare([H1|_], [H2|_]) -> ct:fail(different); compare([], []) -> ok. -start_node(Name, Args) -> - case test_server:start_node(Name, slave, [{args,Args}]) of - {ok,Node} -> {ok, Node}; - Error -> ct:fail(Error) - end. - load_and_call(Out, Module) -> io:format("Loading...\n",[]), code:purge(Module), @@ -350,10 +344,8 @@ otp_7223_2({a}) -> 1. coverage(Config) when is_list(Config) -> - Mod = bsdecode, + Mod = attribute, Src = filename:join(proplists:get_value(data_dir, Config), Mod), {ok,Mod,_} = compile:file(Src, [binary,report,{inline,0}, clint,ssalint]), - {ok,Mod,_} = compile:file(Src, [binary,report,{inline,20}, - verbose,clint,ssalint]), ok. diff --git a/lib/compiler/test/inline_SUITE_data/barnes2.erl b/lib/compiler/test/inline_SUITE_data/barnes2.erl index a986331060..49e9bdfb6b 100644 --- a/lib/compiler/test/inline_SUITE_data/barnes2.erl +++ b/lib/compiler/test/inline_SUITE_data/barnes2.erl @@ -6,7 +6,7 @@ ?MODULE() -> Stars = create_scenario(1000, 1.0), R = hd(loop(10,1000.0,Stars,0)), - Str = lists:flatten(io:lib_format("~s", [R])), + Str = lists:flatten(io_lib:format("~p", [R])), {R,Str =:= {1.00000,-1.92269e+4,-1.92269e+4,2.86459e-2,2.86459e-2}}. create_scenario(N, M) -> diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index 60ab969929..94bfbb0efe 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -25,7 +25,7 @@ match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1, selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1, coverage/1,grab_bag/1,literal_binary/1, - unary_op/1,eq_types/1]). + unary_op/1,eq_types/1,match_after_return/1]). -include_lib("common_test/include/ct.hrl"). @@ -40,7 +40,8 @@ groups() -> match_in_call,untuplify, shortcut_boolean,letify_guard,selectify,deselectify, underscore,match_map,map_vars_used,coverage, - grab_bag,literal_binary,unary_op,eq_types]}]. + grab_bag,literal_binary,unary_op,eq_types, + match_after_return]}]. init_per_suite(Config) -> @@ -890,5 +891,15 @@ eq_types(A, B) -> Ref22. +match_after_return(Config) when is_list(Config) -> + %% The return type of the following call will never match the 'wont_happen' + %% clauses below, and the beam_ssa_type was clever enough to see that but + %% didn't remove the blocks, so it crashed when trying to extract A. + ok = case mar_test_tuple(erlang:unique_integer()) of + {gurka, never_matches, A} -> {wont_happen, A}; + _ -> ok + end. + +mar_test_tuple(I) -> {gurka, I}. id(I) -> I. diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index e999c8ffae..a0b415ceaa 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -161,14 +161,13 @@ md5_1(Beam) -> %% Cover some code that handles internal errors. silly_coverage(Config) when is_list(Config) -> - %% sys_core_fold, sys_core_alias, sys_core_bsm, sys_core_setel, v3_kernel + %% sys_core_fold, sys_core_alias, sys_core_bsm, v3_kernel BadCoreErlang = {c_module,[], name,[],[], [{{c_var,[],{foo,2}},seriously_bad_body}]}, expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end), expect_error(fun() -> sys_core_alias:module(BadCoreErlang, []) end), expect_error(fun() -> sys_core_bsm:module(BadCoreErlang, []) end), - expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end), expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end), %% beam_kernel_to_ssa @@ -185,7 +184,6 @@ silly_coverage(Config) when is_list(Config) -> %% beam_ssa_recv %% beam_ssa_share %% beam_ssa_pre_codegen - %% beam_ssa_opt %% beam_ssa_codegen BadSSA = {b_module,#{},a,b,c, [{b_function,#{func_info=>{mod,foo,0}},args,bad_blocks,0}]}, @@ -193,9 +191,15 @@ silly_coverage(Config) when is_list(Config) -> expect_error(fun() -> beam_ssa_recv:module(BadSSA, []) end), expect_error(fun() -> beam_ssa_share:module(BadSSA, []) end), expect_error(fun() -> beam_ssa_pre_codegen:module(BadSSA, []) end), - expect_error(fun() -> beam_ssa_opt:module(BadSSA, []) end), expect_error(fun() -> beam_ssa_codegen:module(BadSSA, []) end), + %% beam_ssa_opt + BadSSABlocks = #{0 => {b_blk,#{},[bad_code],{b_ret,#{},arg}}}, + BadSSAOpt = {b_module,#{},a,[],c, + [{b_function,#{func_info=>{mod,foo,0}},[], + BadSSABlocks,0}]}, + expect_error(fun() -> beam_ssa_opt:module(BadSSAOpt, []) end), + %% beam_ssa_lint, beam_ssa_pp {error,[{_,Errors}]} = beam_ssa_lint:module(bad_ssa_lint_input(), []), _ = [io:put_chars(Mod:format_error(Reason)) || diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index 12108445f0..0038eb1a4b 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -25,7 +25,8 @@ init_per_group/2,end_per_group/2, 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]). + wait/1,recv_in_try/1,double_recv/1,receive_var_zero/1, + match_built_terms/1]). -include_lib("common_test/include/ct.hrl"). @@ -45,7 +46,8 @@ all() -> groups() -> [{p,test_lib:parallel(), [recv,coverage,otp_7980,ref_opt,export,wait, - recv_in_try,double_recv,receive_var_zero]}]. + recv_in_try,double_recv,receive_var_zero, + match_built_terms]}]. init_per_suite(Config) -> @@ -400,5 +402,29 @@ receive_var_zero(Config) when is_list(Config) -> zero() -> 0. +%% ERL-862; the validator would explode when a term was constructed in a +%% receive guard. + +-define(MATCH_BUILT_TERM(Ref, Expr), + (fun() -> + Ref = make_ref(), + A = id($a), + B = id($b), + Built = id(Expr), + self() ! {Ref, A, B}, + receive + {Ref, A, B} when Expr =:= Built -> + ok + after 5000 -> + ct:fail("Failed to match message with term built in " + "receive guard.") + end + end)()). + +match_built_terms(Config) when is_list(Config) -> + ?MATCH_BUILT_TERM(Ref, [A, B]), + ?MATCH_BUILT_TERM(Ref, {A, B}), + ?MATCH_BUILT_TERM(Ref, <<A, B>>), + ?MATCH_BUILT_TERM(Ref, #{ 1 => A, 2 => B}). id(I) -> I. diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index 26149e11e6..39c26c6142 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -50,12 +50,8 @@ smoke_disasm(File) when is_list(File) -> Res = beam_disasm:file(File), {beam_file,_Mod} = {element(1, Res),element(2, Res)}. -%% If we are running cover, we don't want to run test cases that -%% invokes the compiler in parallel, as doing so would probably -%% be slower than running them sequentially. - parallel() -> - case test_server:is_cover() orelse erlang:system_info(schedulers) =:= 1 of + case erlang:system_info(schedulers) =:= 1 of true -> []; false -> [parallel] end. @@ -70,21 +66,24 @@ uniq() -> opt_opts(Mod) -> Comp = Mod:module_info(compile), {options,Opts} = lists:keyfind(options, 1, Comp), - lists:filter(fun(no_copt) -> true; - (no_postopt) -> true; - (no_ssa_opt) -> true; - (no_recv_opt) -> true; - (no_ssa_float) -> true; - (no_stack_trimming) -> true; - (debug_info) -> true; - (inline) -> true; - (no_put_tuple2) -> true; - (no_bsm3) -> true; - (no_bsm_opt) -> true; - (no_module_opt) -> true; - (no_type_opt) -> true; - (_) -> false - end, Opts). + lists:filter(fun + (debug_info) -> true; + (inline) -> true; + (no_bsm3) -> true; + (no_bsm_opt) -> true; + (no_copt) -> true; + (no_fun_opt) -> true; + (no_module_opt) -> true; + (no_postopt) -> true; + (no_put_tuple2) -> true; + (no_recv_opt) -> true; + (no_share_opt) -> true; + (no_ssa_float) -> true; + (no_ssa_opt) -> true; + (no_stack_trimming) -> true; + (no_type_opt) -> true; + (_) -> false + end, Opts). %% Some test suites gets cloned (e.g. to "record_SUITE" to %% "record_no_opt_SUITE"), but the data directory is not cloned. @@ -97,18 +96,20 @@ get_data_dir(Config) -> Data2 = re:replace(Data1, "_post_opt_SUITE", "_SUITE", Opts), Data3 = re:replace(Data2, "_inline_SUITE", "_SUITE", Opts), Data4 = re:replace(Data3, "_r21_SUITE", "_SUITE", Opts), - re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts). + Data = re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts), + re:replace(Data, "_no_ssa_opt_SUITE", "_SUITE", Opts). is_cloned_mod(Mod) -> is_cloned_mod_1(atom_to_list(Mod)). %% Test whether Mod is a cloned module. -is_cloned_mod_1("no_opt_SUITE") -> true; -is_cloned_mod_1("post_opt_SUITE") -> true; -is_cloned_mod_1("inline_SUITE") -> true; -is_cloned_mod_1("21_SUITE") -> true; -is_cloned_mod_1("no_module_opt_SUITE") -> true; +is_cloned_mod_1("_no_opt_SUITE") -> true; +is_cloned_mod_1("_no_ssa_opt_SUITE") -> true; +is_cloned_mod_1("_post_opt_SUITE") -> true; +is_cloned_mod_1("_inline_SUITE") -> true; +is_cloned_mod_1("_21_SUITE") -> true; +is_cloned_mod_1("_no_module_opt_SUITE") -> true; is_cloned_mod_1([_|T]) -> is_cloned_mod_1(T); is_cloned_mod_1([]) -> false. @@ -117,18 +118,7 @@ is_cloned_mod_1([]) -> false. p_run(Test, List) -> S = erlang:system_info(schedulers), - N = case test_server:is_cover() of - false -> - S + 1; - true -> - %% Cover is running. Using too many processes - %% could slow us down. Measurements on my computer - %% showed that using 4 parallel processes was - %% slightly faster than using 3. Using more than - %% 4 would not buy us much and could actually be - %% slower. - min(S, 4) - end, + N = S + 1, io:format("p_run: ~p parallel processes\n", [N]), p_run_loop(Test, List, N, [], 0, 0). diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl index 1f39348998..70b7100451 100644 --- a/lib/compiler/test/warnings_SUITE.erl +++ b/lib/compiler/test/warnings_SUITE.erl @@ -42,7 +42,7 @@ comprehensions/1,maps/1,maps_bin_opt_info/1, redundant_boolean_clauses/1, latin1_fallback/1,underscore/1,no_warnings/1, - bit_syntax/1,inlining/1]). + bit_syntax/1,inlining/1,tuple_calls/1]). init_per_testcase(_Case, Config) -> Config. @@ -64,7 +64,8 @@ groups() -> bin_opt_info,bin_construction,comprehensions,maps, maps_bin_opt_info, redundant_boolean_clauses,latin1_fallback, - underscore,no_warnings,bit_syntax,inlining]}]. + underscore,no_warnings,bit_syntax,inlining, + tuple_calls]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), @@ -239,19 +240,7 @@ guard(Config) when is_list(Config) -> {4,sys_core_fold,nomatch_guard}, {6,sys_core_fold,no_clause_match}, {6,sys_core_fold,nomatch_guard}, - {6,sys_core_fold,{eval_failure,badarg}}, - {8,sys_core_fold,no_clause_match}, - {8,sys_core_fold,nomatch_guard}, - {8,sys_core_fold,{eval_failure,badarg}}, - {9,sys_core_fold,no_clause_match}, - {9,sys_core_fold,nomatch_guard}, - {9,sys_core_fold,{eval_failure,badarg}}, - {10,sys_core_fold,no_clause_match}, - {10,sys_core_fold,nomatch_guard}, - {10,sys_core_fold,{eval_failure,badarg}}, - {11,sys_core_fold,no_clause_match}, - {11,sys_core_fold,nomatch_guard}, - {11,sys_core_fold,{eval_failure,badarg}} + {6,sys_core_fold,{eval_failure,badarg}} ]}}], [] = run(Config, Ts), @@ -970,6 +959,20 @@ inlining(Config) -> run(Config, Ts), ok. +tuple_calls(Config) -> + %% Make sure that no spurious warnings are generated. + Ts = [{inlining_1, + <<"-compile(tuple_calls). + dispatch(X) -> + (list_to_atom(\"prefix_\" ++ + atom_to_list(suffix))):doit(X). + ">>, + [], + []} + ], + run(Config, Ts), + ok. + %%% %%% End of test cases. %%% |