diff options
author | John Högberg <[email protected]> | 2018-10-05 14:33:01 +0200 |
---|---|---|
committer | John Högberg <[email protected]> | 2018-10-05 15:43:14 +0200 |
commit | d6509e377db65f2afd7394db2a5154e420dfd4dc (patch) | |
tree | b0f90aaafa4ae081412ad0412119456d172e9bcb | |
parent | 1b4ad9a2d65a094285a40ae8507bc5b46a59b2e9 (diff) | |
download | otp-d6509e377db65f2afd7394db2a5154e420dfd4dc.tar.gz otp-d6509e377db65f2afd7394db2a5154e420dfd4dc.tar.bz2 otp-d6509e377db65f2afd7394db2a5154e420dfd4dc.zip |
beam_ssa_pre_codegen: Literal funs need stack frames too
Fixes a crash during code generation of the following code:
call_atom() ->
fun({send = Send}) ->
Send()
end.
-rw-r--r-- | lib/compiler/src/beam_ssa_pre_codegen.erl | 8 | ||||
-rw-r--r-- | lib/compiler/test/fun_SUITE.erl | 7 |
2 files changed, 11 insertions, 4 deletions
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index 40742e441a..9175931375 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -1043,11 +1043,11 @@ need_frame_1([#b_set{op=call,args=[Func|_]}|Is], Context) -> #b_remote{} -> %% This is an apply(), which always needs a frame. true; - #b_var{} -> - %% A fun call always needs a frame. - true; + #b_local{} -> + Context =:= body orelse Is =/= []; _ -> - Context =:= body orelse Is =/= [] + %% A fun call always needs a frame. + true end; need_frame_1([I|Is], Context) -> beam_ssa:clobbers_xregs(I) orelse need_frame_1(Is, Context); diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl index e00885fcd6..1df0a05275 100644 --- a/lib/compiler/test/fun_SUITE.erl +++ b/lib/compiler/test/fun_SUITE.erl @@ -249,6 +249,13 @@ badfun(_Config) -> expect_badfun(X, catch X(put(?FUNCTION_NAME, of_course))), of_course = erase(?FUNCTION_NAME), + %% A literal as a Fun used to crash the code generator. This only happened + %% when type optimization had reduced `Fun` to a literal, hence the match. + Literal = fun(literal = Fun) -> + Fun() + end, + expect_badfun(literal, catch Literal(literal)), + ok. expect_badfun(Term, Exit) -> |