aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/v3_core.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2010-03-18 08:45:03 +0100
committerBjörn Gustavsson <[email protected]>2010-03-26 08:09:26 +0100
commit0320836d1b58438ef4467832b00306672d22f8d6 (patch)
tree6953fb68c2c04e162ecb7e5cd9a568a43ceacddf /lib/compiler/src/v3_core.erl
parente74235df989995f5bd2b66b7102857446ff10d11 (diff)
downloadotp-0320836d1b58438ef4467832b00306672d22f8d6.tar.gz
otp-0320836d1b58438ef4467832b00306672d22f8d6.tar.bz2
otp-0320836d1b58438ef4467832b00306672d22f8d6.zip
Consistently rewrite an inlined function_clause exception to case_clause
A function_clause exception is generated by jumping to a func_info/3 instruction at the beginning of the function. The x registers are assumed to contain the arguments for the function. That means that a func_info/3 instruction copied from another function (or even from the same function if not at the top level) will not work, so it must be replaced with an instruction that generates a case_clause exception. In Core Erlang, a func_info/3 instruction is represented as a the primop match_fail({function_clause,Arg1,...ArgN}). The current mechanism that is supposed to replace the primop match_fail(function_clause) with match_fail(case_clause) will fail to do that in the following circumstances: 1. If the inliner has inlined a function into itself. Fix that by having the inliner clear the function_name annotations on all match_fail primops in functions that are inlined. (To simplify doing that, the annotation is now on the primop node itself and not on the 'function_clause' atom inside it.) 2. If the inliner has rewritten the tuple node in the primop node to a literal (when inlining a function call with literal arguments), v3_kernel would not recognize the match_fail(function_clause) primop and would not rewrite it. Fix it by making v3_kernel smarter. Also simplify the "old" inliner (sys_core_inline) to only clear the function_name annotations instead of rewriting function_clause execptions to case_clause execptions itself.
Diffstat (limited to 'lib/compiler/src/v3_core.erl')
-rw-r--r--lib/compiler/src/v3_core.erl22
1 files changed, 13 insertions, 9 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 8b04969b05..4ac2196d79 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1542,17 +1542,21 @@ new_vars_1(N, Anno, St0, Vs) when N > 0 ->
new_vars_1(0, _, St, Vs) -> {Vs,St}.
function_clause(Ps, Name) ->
- fail_clause(Ps, c_tuple([#c_literal{anno=[{name,Name}],
- val=function_clause}|Ps])).
-function_clause(Ps, Anno, Name) ->
- fail_clause(Ps, ann_c_tuple(Anno,
- [#c_literal{anno=[{name,Name}],
- val=function_clause}|Ps])).
-
-fail_clause(Pats, A) ->
+ function_clause(Ps, [], Name).
+
+function_clause(Ps, LineAnno, Name) ->
+ FcAnno = [{function_name,Name}],
+ fail_clause(Ps, FcAnno,
+ ann_c_tuple(LineAnno, [#c_literal{val=function_clause}|Ps])).
+
+fail_clause(Pats, Arg) ->
+ fail_clause(Pats, [], Arg).
+
+fail_clause(Pats, Anno, Arg) ->
#iclause{anno=#a{anno=[compiler_generated]},
pats=Pats,guard=[],
- body=[#iprimop{anno=#a{},name=#c_literal{val=match_fail},args=[A]}]}.
+ body=[#iprimop{anno=#a{anno=Anno},name=#c_literal{val=match_fail},
+ args=[Arg]}]}.
ubody(B, St) -> uexpr(B, [], St).