aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/v3_life.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2011-12-21 06:44:28 +0100
committerBjörn Gustavsson <[email protected]>2012-01-04 10:49:15 +0100
commit53bd4974a1012669fb7db09815fabac01b586c12 (patch)
treec2c1bc82febe57acf81969bee72b57af4181f308 /lib/compiler/src/v3_life.erl
parent8769a849dbbb70cb92733f484b2a0e1693e97eb7 (diff)
downloadotp-53bd4974a1012669fb7db09815fabac01b586c12.tar.gz
otp-53bd4974a1012669fb7db09815fabac01b586c12.tar.bz2
otp-53bd4974a1012669fb7db09815fabac01b586c12.zip
Eliminate the match_fail primop in v3_kernel and later passes
In the v3_life pass, it is assumed that a 'match_fail' primop only occur at the top-level and at the end of a function. But this code: do_split_cases(A) -> case A of x -> Z = dummy1; _ -> Z = dummy2, a=b end, Z. will be optimized by sys_core_fold to the following code: 'split_cases'/1 = fun (_cor0) -> let <_cor7,Z> = case _cor0 of <'x'> when 'true' -> < 'dummy1','dummy1' > <_cor6> when 'true' -> %% Here follows a 'match_fail' primop inside %% multiple return values: < primop 'match_fail'({'badmatch','b'}),'dummy2' > end in Z moving the 'match_fail' primop into a "values" construction. In the future, we would like to get rid of the v3_life pass (it is there for historical reasons), so in the mean-time we prefer to not add more code to it by generalizing the handling of 'match_fail'. Since the 'match_fail' primop can be simulated by erlang:error/{1,2}, the simplest solution is to translate 'match_fail' to a call to erlang:error/{1,2} in v3_kernel and remove the handling of 'match_fail' in v3_life and v3_codegen. It is tempting to get rid of 'match_fail' also in the Core Erlang format, but there are two issues: - Removing the support for 'match_fail' completely may break tools that generate Core Erlang code. We should not do that in a minor release. - There is no easy way to generate a 'function_clause' exception that will remain correct if it will be inlined into another function. (Calling "erlang:error(function_clause, Args)" is fine only if it is not inlined into another function.) A good solution probably involves introducing new instructions, which is better done in a major release. Noticed-by: Håkan Matsson Minimized-test-case-by: Erik Søe Sørensen
Diffstat (limited to 'lib/compiler/src/v3_life.erl')
-rw-r--r--lib/compiler/src/v3_life.erl34
1 files changed, 2 insertions, 32 deletions
diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl
index fac9a9843d..93f8034230 100644
--- a/lib/compiler/src/v3_life.erl
+++ b/lib/compiler/src/v3_life.erl
@@ -89,19 +89,8 @@ function(#k_fdef{anno=#k{a=Anno},func=F,arity=Ar,vars=Vs,body=Kb}) ->
end.
%% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
-%% Handle a body, need special cases for transforming match_fails.
-%% We KNOW that they only occur last in a body.
-
-body(#k_seq{arg=#k_put{anno=Pa,arg=Arg,ret=[R]},
- body=#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},
- args=[R]}},
- I, Vdb0) ->
- Vdb1 = use_vars(Pa#k.us, I, Vdb0), %All used here
- {[match_fail(Arg, I, Pa#k.a ++ Ea#k.a)],I,Vdb1};
-body(#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},args=[Arg]},
- I, Vdb0) ->
- Vdb1 = use_vars(Ea#k.us, I, Vdb0),
- {[match_fail(Arg, I, Ea#k.a)],I,Vdb1};
+%% Handle a body.
+
body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
%%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
A = get_kanno(Ke),
@@ -353,25 +342,6 @@ guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Ctxt, Vdb0) ->
i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1),
a=A#k.a}.
-%% match_fail(FailValue, I, Anno) -> Expr.
-%% Generate the correct match_fail instruction. N.B. there is no
-%% generic case for when the fail value has been created elsewhere.
-
-match_fail(#k_literal{anno=Anno,val={Atom,Val}}, I, A) when is_atom(Atom) ->
- match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom},#k_literal{val=Val}]}, I, A);
-match_fail(#k_literal{anno=Anno,val={Atom}}, I, A) when is_atom(Atom) ->
- match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom}]}, I, A);
-match_fail(#k_tuple{es=[#k_atom{val=function_clause}|As]}, I, A) ->
- #l{ke={match_fail,{function_clause,literal_list(As, [])}},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=badmatch},Val]}, I, A) ->
- #l{ke={match_fail,{badmatch,literal(Val, [])}},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=case_clause},Val]}, I, A) ->
- #l{ke={match_fail,{case_clause,literal(Val, [])}},i=I,a=A};
-match_fail(#k_atom{val=if_clause}, I, A) ->
- #l{ke={match_fail,if_clause},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=try_clause},Val]}, I, A) ->
- #l{ke={match_fail,{try_clause,literal(Val, [])}},i=I,a=A}.
-
%% type(Ktype) -> Type.
type(k_literal) -> literal;