diff options
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/Makefile | 3 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_type.erl | 23 | ||||
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 10 | ||||
-rw-r--r-- | lib/compiler/src/compile.erl | 12 | ||||
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 45 |
5 files changed, 40 insertions, 53 deletions
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index c971e8844d..9f8d63baa1 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -129,9 +129,10 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE) ifeq ($(NATIVE_LIBS_ENABLED),yes) ERL_COMPILE_FLAGS += +native +else +ERL_COMPILE_FLAGS += -Werror endif ERL_COMPILE_FLAGS += +inline +warn_unused_import \ - -Werror \ -I../../stdlib/include -I$(EGEN) -W +warn_missing_spec # ---------------------------------------------------- diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index c01ea4af91..06b42f1928 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -267,10 +267,29 @@ opt_is([#b_set{op=call,args=Args0,dst=Dst}=I0|Is], I1 = beam_ssa:normalize(I0#b_set{args=Args}), {Ts1,Ds,Fdb,I2} = opt_call(I1, D, Ts0, Ds0, Fdb0), case {map_get(Dst, Ts1),Is} of - {_,[#b_set{op=succeeded}]} -> + {Type,[#b_set{op=succeeded}]} when Type =/= none -> %% This call instruction is inside a try/catch - %% block. Don't attempt to optimize it. + %% block. Don't attempt to simplify it. opt_is(Is, Ts1, Ds, Fdb, D, Sub0, [I2|Acc]); + {none,[#b_set{op=succeeded}]} -> + %% This call instruction is inside a try/catch + %% block, but we know it will never return and + %% later optimizations may try to exploit that. + %% + %% For example, if we have an expression that + %% either returns this call or a tuple, we know + %% that the expression always returns a tuple + %% and can turn a later element/3 into + %% get_tuple_element. + %% + %% This is sound but difficult to validate in a + %% meaningful way as try/catch currently forces + %% us to maintain the illusion that the success + %% block is reachable even when its not, so we + %% disable the optimization to keep things + %% simple. + Ts = Ts1#{ Dst := any }, + opt_is(Is, Ts, Ds, Fdb, D, Sub0, [I2|Acc]); {none,_} -> %% This call never returns. The rest of the %% instructions will not be executed. diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 4fba3fa1c6..efd2be94cb 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -2899,8 +2899,6 @@ lists_mod_return_type(filter, 2, _Vst) -> list; lists_mod_return_type(flatten, 1, _Vst) -> list; -lists_mod_return_type(flatten, 2, _Vst) -> - list; lists_mod_return_type(map, 2, Vst) -> same_length_type({x,1}, Vst); lists_mod_return_type(MF, 3, Vst) when MF =:= mapfoldl; MF =:= mapfoldr -> @@ -2912,8 +2910,6 @@ lists_mod_return_type(reverse, 1, Vst) -> same_length_type({x,0}, Vst); lists_mod_return_type(seq, 2, _Vst) -> list; -lists_mod_return_type(seq, 3, _Vst) -> - list; lists_mod_return_type(sort, 1, Vst) -> same_length_type({x,0}, Vst); lists_mod_return_type(sort, 2, Vst) -> @@ -2927,16 +2923,10 @@ lists_mod_return_type(unzip, 1, Vst) -> two_tuple(ListType, ListType); lists_mod_return_type(usort, 1, Vst) -> same_length_type({x,0}, Vst); -lists_mod_return_type(usort, 2, Vst) -> - same_length_type({x,1}, Vst); lists_mod_return_type(zip, 2, _Vst) -> list; -lists_mod_return_type(zip3, 3, _Vst) -> - list; lists_mod_return_type(zipwith, 3, _Vst) -> list; -lists_mod_return_type(zipwith3, 4, _Vst) -> - list; lists_mod_return_type(_, _, _) -> term. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 11dea9524b..28db8986ff 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -290,6 +290,10 @@ format_error(bad_crypto_key) -> "invalid crypto key."; format_error(no_crypto_key) -> "no crypto key supplied."; +format_error({unimplemented_instruction,Instruction}) -> + io_lib:fwrite("native-code compilation failed because of an " + "unimplemented instruction (~s).", + [Instruction]); format_error({native, E}) -> io_lib:fwrite("native-code compilation failed with reason: ~tP.", [E, 25]); @@ -1651,18 +1655,22 @@ native_compile_1(Code, St) -> case IgnoreErrors of true -> Ws = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}], - {ok,St#compile{warnings=St#compile.warnings ++ Ws}}; + {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}}; false -> Es = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}], {error,St#compile{errors=St#compile.errors ++ Es}} end catch + exit:{unimplemented_instruction,_}=Unimplemented -> + Ws = [{St#compile.ifile, + [{none,?MODULE,Unimplemented}]}], + {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}}; Class:R:Stack -> case IgnoreErrors of true -> Ws = [{St#compile.ifile, [{none,?MODULE,{native_crash,R,Stack}}]}], - {ok,St#compile{warnings=St#compile.warnings ++ Ws}}; + {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}}; false -> erlang:raise(Class, R, Stack) end diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 7e219da0af..4939a94a92 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -1997,53 +1997,22 @@ case_opt_compiler_generated(Core) -> %% case_expand_var(Expr0, Sub) -> Expr -%% If Expr0 is a variable that has been previously matched and -%% is known to be a tuple, return the tuple instead. Otherwise +%% If Expr0 is a variable that is known to be bound to a +%% constructed tuple, return the tuple instead. Otherwise %% return Expr0 unchanged. -%% + case_expand_var(E, #sub{t=Tdb}) -> Key = cerl:var_name(E), case Tdb of - #{Key:=T0} -> - case cerl:is_c_tuple(T0) of - false -> - E; - true -> - %% The pattern was a tuple. Now we must make sure - %% that the elements of the tuple are suitable. In - %% particular, we don't want binary or map - %% construction here, since that means that the - %% binary or map will be constructed in the 'case' - %% argument. That is wasteful for binaries. Even - %% worse is that any map pattern that use the ':=' - %% operator will fail when used in map - %% construction (only the '=>' operator is allowed - %% when constructing a map from scratch). - try - cerl_trees:map(fun coerce_to_data/1, T0) - catch - throw:impossible -> - %% Something unsuitable was found (map or - %% or binary). Keep the variable. - E - end + #{Key:=T} -> + case cerl:is_c_tuple(T) of + false -> E; + true -> T end; _ -> E end. -%% coerce_to_data(Core) -> Core' -%% Coerce an element originally from a pattern to an data item or or -%% variable. Throw an 'impossible' exception if non-data Core Erlang -%% terms such as binary construction or map construction are -%% encountered. - -coerce_to_data(C) -> - case cerl:is_data(C) orelse cerl:is_c_var(C) of - true -> C; - false -> throw(impossible) - end. - %% case_opt_nomatch(E, Clauses, LitExpr) -> Clauses' %% Remove all clauses that cannot possibly match. |