From 53bd4974a1012669fb7db09815fabac01b586c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 21 Dec 2011 06:44:28 +0100 Subject: Eliminate the match_fail primop in v3_kernel and later passes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- lib/compiler/test/compilation_SUITE.erl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'lib/compiler/test') 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. -- cgit v1.2.3