aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src')
-rw-r--r--lib/compiler/src/Makefile3
-rw-r--r--lib/compiler/src/beam_ssa_type.erl23
-rw-r--r--lib/compiler/src/beam_validator.erl10
-rw-r--r--lib/compiler/src/compile.erl12
-rw-r--r--lib/compiler/src/sys_core_fold.erl45
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.