diff options
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/Makefile | 15 | ||||
-rw-r--r-- | lib/compiler/test/beam_ssa_SUITE.erl | 96 | ||||
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 25 | ||||
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 22 | ||||
-rw-r--r-- | lib/compiler/test/bs_match_SUITE.erl | 19 | ||||
-rw-r--r-- | lib/compiler/test/match_SUITE.erl | 21 | ||||
-rw-r--r-- | lib/compiler/test/test_lib.erl | 3 |
7 files changed, 188 insertions, 13 deletions
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index db8eb7e2e1..7be23fbb93 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -109,6 +109,8 @@ NO_MOD_OPT = $(NO_OPT) NO_SSA_OPT = $(NO_OPT) +NO_TYPE_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) @@ -121,6 +123,8 @@ 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) +NO_TYPE_OPT_MODULES= $(NO_TYPE_OPT:%=%_no_type_opt_SUITE) +NO_TYPE_OPT_ERL_FILES= $(NO_TYPE_OPT_MODULES:%=%.erl) ERL_FILES= $(MODULES:%=%.erl) CORE_FILES= $(CORE_MODULES:%=%.core) @@ -150,7 +154,7 @@ EBIN = . # ---------------------------------------------------- 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) + $(INLINE_ERL_FILES) $(R21_ERL_FILES) $(NO_MOD_OPT_ERL_FILES) $(NO_TYPE_OPT_ERL_FILES) $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ > $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt \ @@ -169,6 +173,8 @@ make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES -o$(EBIN) $(NO_MOD_OPT_MODULES) >> $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +from_core $(ERL_COMPILE_FLAGS) \ -o$(EBIN) $(CORE_MODULES) >> $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +no_type_opt $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(NO_TYPE_OPT_MODULES) >> $(EMAKEFILE) tests debug opt: make_emakefile erl $(ERL_MAKE_FLAGS) -make @@ -202,6 +208,10 @@ docs: %_no_module_opt_SUITE.erl: %_SUITE.erl sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ +%_no_type_opt_SUITE.erl: %_SUITE.erl + sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ + + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- @@ -216,7 +226,8 @@ release_tests_spec: make_emakefile $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \ $(INLINE_ERL_FILES) $(R21_ERL_FILES) \ $(NO_MOD_OPT_ERL_FILES) \ - $(NO_SSA_OPT_ERL_FILES) "$(RELSYSDIR)" + $(NO_SSA_OPT_ERL_FILES) \ + $(NO_TYPE_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_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index a741ebbdf9..3b510f3528 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -23,7 +23,7 @@ init_per_group/2,end_per_group/2, calls/1,tuple_matching/1,recv/1,maps/1, cover_ssa_dead/1,combine_sw/1,share_opt/1, - beam_ssa_dead_crash/1]). + beam_ssa_dead_crash/1,stack_init/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -39,7 +39,8 @@ groups() -> cover_ssa_dead, combine_sw, share_opt, - beam_ssa_dead_crash + beam_ssa_dead_crash, + stack_init ]}]. init_per_suite(Config) -> @@ -190,6 +191,15 @@ recv(_Config) -> self() ! {[self(),r1],{2,99,<<"data">>}}, {Parent,r1,<<1:32,2:8,99:8,"data">>} = tricky_recv_4(), + %% Test tricky_recv_5/0. + self() ! 1, + a = tricky_recv_5(), + self() ! 2, + b = tricky_recv_5(), + + %% tricky_recv_6/0 is a compile-time error. + tricky_recv_6(), + ok. sync_wait_mon({Pid, Ref}, Timeout) -> @@ -295,6 +305,38 @@ tricky_recv_4() -> end, id({Pid,R,Request}). +%% beam_ssa_pre_codegen would accidentally create phi nodes on critical edges +%% when fixing up receives; the call to id/2 can either succeed or land in the +%% catch block, and we added a phi node to its immediate successor. +tricky_recv_5() -> + try + receive + X=1 -> + id(42), + a; + X=2 -> + b + end, + case X of + 1 -> a; + 2 -> b + end + catch + _:_ -> c + end. + +%% When fixing tricky_recv_5, we introduced a compiler crash when the common +%% exit block was ?BADARG_BLOCK and floats were in the picture. +tricky_recv_6() -> + RefA = make_ref(), + RefB = make_ref(), + receive + {RefA, Number} -> Number + 1.0; + {RefB, Number} -> Number + 2.0 + after 0 -> + ok + end. + maps(_Config) -> {'EXIT',{{badmatch,#{}},_}} = (catch maps_1(any)), ok. @@ -483,9 +525,11 @@ do_comb_sw_2(X) -> erase(?MODULE). share_opt(_Config) -> - ok = do_share_opt(0). + ok = do_share_opt_1(0), + ok = do_share_opt_2(), + ok. -do_share_opt(A) -> +do_share_opt_1(A) -> %% The compiler would be stuck in an infinite loop in beam_ssa_share. case A of 0 -> a; @@ -494,6 +538,26 @@ do_share_opt(A) -> end, receive after 1 -> ok end. +do_share_opt_2() -> + ok = sopt_2({[pointtopoint], [{dstaddr,any}]}, ok), + ok = sopt_2({[broadcast], [{broadaddr,any}]}, ok), + ok = sopt_2({[], []}, ok), + ok. + +sopt_2({Flags, Opts}, ok) -> + Broadcast = lists:member(broadcast, Flags), + P2P = lists:member(pointtopoint, Flags), + case Opts of + %% The following two clauses would be combined to one, silently + %% discarding the guard test of the P2P variable. + [{broadaddr,_}|Os] when Broadcast -> + sopt_2({Flags, Os}, ok); + [{dstaddr,_}|Os] when P2P -> + sopt_2({Flags, Os}, ok); + [] -> + ok + end. + beam_ssa_dead_crash(_Config) -> not_A_B = do_beam_ssa_dead_crash(id(false), id(true)), not_A_not_B = do_beam_ssa_dead_crash(false, false), @@ -548,6 +612,30 @@ do_beam_ssa_dead_crash(A, B) -> end end. +stack_init(_Config) -> + 6 = stack_init(a, #{a => [1,2,3]}), + 0 = stack_init(missing, #{}), + ok. + +stack_init(Key, Map) -> + %% beam_ssa_codegen would wrongly assume that y(0) would always be + %% initialized by the `get_map_elements` instruction that follows, and + %% would set up the stack frame using an `allocate` instruction and + %% would not generate an `init` instruction to initialize y(0). + Res = case Map of + #{Key := Elements} -> + %% Elements will be assigned to y(0) if the key Key exists. + lists:foldl(fun(El, Acc) -> + Acc + El + end, 0, Elements); + #{} -> + %% y(0) will be left uninitialized when the key is not + %% present in the map. + 0 + end, + %% y(0) would be uninitialized here if the key was not present in the map + %% (if the second clause was executed). + id(Res). %% The identity function. id(I) -> I. diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 076a604aa4..a99dee48aa 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -24,7 +24,8 @@ integers/1,numbers/1,coverage/1,booleans/1,setelement/1, cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1, arity_checks/1,elixir_binaries/1,find_best/1, - test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1]). + test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1, + none_argument/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -49,7 +50,8 @@ groups() -> test_size, cover_lists_functions, list_append, - bad_binary_unit + bad_binary_unit, + none_argument ]}]. init_per_suite(Config) -> @@ -518,5 +520,24 @@ bad_binary_unit(_Config) -> false = is_binary(Bitstring), ok. +%% ERL-1013: The compiler would crash during the type optimization pass. +none_argument(_Config) -> + Binary = id(<<3:16, 42>>), + error = id(case Binary of + <<Len:16, Body/binary>> when length(Body) == Len - 2 -> + %% The type for Body will be none. It means + %% that this clause will never match and that + %% uncompress/1 will never be called. + uncompress(Body); + _ -> + error + end), + ok. + +uncompress(CompressedBinary) -> + %% The type for CompressedBinary is none, which beam_ssa_type + %% did not handle properly. + zlib:uncompress(CompressedBinary). + id(I) -> I. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 6b1438abdd..20f6cb2691 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -681,11 +681,16 @@ infer_on_eq_4(T) -> %% ERIERL-348; types were inferred for dead values, causing validation to fail. +-record(idv, {key}). + infer_dead_value(Config) when is_list(Config) -> a = idv_1({a, b, c, d, e, f, g}, {0, 0, 0, 0, 0, 0, 0}), b = idv_1({a, b, c, d, 0, 0, 0}, {a, b, c, d, 0, 0, 0}), c = idv_1({0, 0, 0, 0, 0, f, g}, {0, 0, 0, 0, 0, f, g}), error = idv_1(gurka, gaffel), + + ok = idv_2(id(#idv{})), + ok. idv_1({_A, _B, _C, _D, _E, _F, _G}, @@ -700,6 +705,23 @@ idv_1({_A, _B, _C, _D, _E, F, G}, idv_1(_A, _B) -> error. +%% ERL-995: The first solution to ERIERL-348 was incomplete and caused +%% validation to fail when living values depended on delayed type inference on +%% "dead" values. + +idv_2(State) -> + Flag = (State#idv.key == undefined), + case id(gurka) of + {_} -> id([Flag]); + _ -> ok + end, + if + Flag -> idv_called_once(State); + true -> ok + end. + +idv_called_once(_State) -> ok. + %%%------------------------------------------------------------------------- transform_remove(Remove, Module) -> diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index d97f49c56e..145a50f4ad 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -44,7 +44,8 @@ beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1, expression_before_match/1,erl_689/1,restore_on_call/1, restore_after_catch/1,matches_on_parameter/1,big_positions/1, - matching_meets_apply/1,bs_start_match2_defs/1]). + matching_meets_apply/1,bs_start_match2_defs/1, + exceptions_after_match_failure/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -80,7 +81,8 @@ groups() -> beam_bsm,guard,is_ascii,non_opt_eq, expression_before_match,erl_689,restore_on_call, matches_on_parameter,big_positions, - matching_meets_apply,bs_start_match2_defs]}]. + matching_meets_apply,bs_start_match2_defs, + exceptions_after_match_failure]}]. init_per_suite(Config) -> @@ -2005,4 +2007,17 @@ do_matching_meets_apply(_Bin, {Handler, State}) -> %% Another case of the above. Handler:abs(State). +%% Exception handling was broken on the failure path of bs_start_match as +%% beam_ssa_bsm accidentally cloned and renamed the ?BADARG_BLOCK. +exceptions_after_match_failure(_Config) -> + {'EXIT', {badarith, _}} = (catch do_exceptions_after_match_failure(atom)), + ok = do_exceptions_after_match_failure(<<0, 1, "gurka">>), + ok = do_exceptions_after_match_failure(2.0). + +do_exceptions_after_match_failure(<<_A, _B, "gurka">>) -> + ok; +do_exceptions_after_match_failure(Other) -> + Other / 2.0, + ok. + id(I) -> I. diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index aac9de278d..bc74ec4984 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -25,7 +25,8 @@ 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,match_after_return/1,match_right_tuple/1]). + unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1, + tuple_size_in_try/1]). -include_lib("common_test/include/ct.hrl"). @@ -41,7 +42,8 @@ groups() -> shortcut_boolean,letify_guard,selectify,deselectify, underscore,match_map,map_vars_used,coverage, grab_bag,literal_binary,unary_op,eq_types, - match_after_return,match_right_tuple]}]. + match_after_return,match_right_tuple, + tuple_size_in_try]}]. init_per_suite(Config) -> @@ -922,4 +924,19 @@ match_right_tuple_1(T) -> force_succ_regs(_A, B) -> B. +tuple_size_in_try(Config) when is_list(Config) -> + %% The tuple_size optimization was applied outside of guards, causing + %% either the emulator or compiler to crash. + ok = tsit(gurka), + ok = tsit(gaffel). + +tsit(A) -> + try + id(ignored), + 1 = tuple_size(A), + error + catch + _:_ -> ok + end. + id(I) -> I. diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index 3348c6e9ea..34410e4b2a 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -97,7 +97,8 @@ 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), - Data = re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts), + Data5 = re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts), + Data = re:replace(Data5, "_no_type_opt_SUITE", "_SUITE", Opts), re:replace(Data, "_no_ssa_opt_SUITE", "_SUITE", Opts). is_cloned_mod(Mod) -> |