aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/test
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2011-12-21 06:44:28 +0100
committerBjörn Gustavsson <bjorn@erlang.org>2012-01-04 10:49:15 +0100
commit53bd4974a1012669fb7db09815fabac01b586c12 (patch)
treec2c1bc82febe57acf81969bee72b57af4181f308 /lib/compiler/test
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/test')
-rw-r--r--lib/compiler/test/compilation_SUITE.erl16
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.