diff options
author | Björn Gustavsson <[email protected]> | 2011-12-21 06:44:28 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2012-01-04 10:49:15 +0100 |
commit | 53bd4974a1012669fb7db09815fabac01b586c12 (patch) | |
tree | c2c1bc82febe57acf81969bee72b57af4181f308 /lib/compiler/test | |
parent | 8769a849dbbb70cb92733f484b2a0e1693e97eb7 (diff) | |
download | otp-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/test')
-rw-r--r-- | lib/compiler/test/compilation_SUITE.erl | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index 1343fbd1c9..1f17664b54 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -44,7 +44,7 @@ all() -> trycatch_4, opt_crash, otp_5404, otp_5436, otp_5481, otp_5553, otp_5632, otp_5714, otp_5872, otp_6121, otp_6121a, otp_6121b, otp_7202, otp_7345, on_load, - string_table,otp_8949_a,otp_8949_a]. + string_table,otp_8949_a,otp_8949_a,split_cases]. groups() -> [{vsn, [], [vsn_1, vsn_2, vsn_3]}]. @@ -657,5 +657,19 @@ otp_8949_b(A, B) -> id(Var) end. +split_cases(_) -> + dummy1 = do_split_cases(x), + {'EXIT',{{badmatch,b},_}} = (catch do_split_cases(y)), + ok. + +do_split_cases(A) -> + case A of + x -> + Z = dummy1; + _ -> + Z = dummy2, + a=b + end, + Z. id(I) -> I. |