aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2016-05-24 09:28:32 +0200
committerBjörn Gustavsson <[email protected]>2016-05-25 16:41:26 +0200
commitca368c8503712dce0044201bf25323ace3372a62 (patch)
tree98b8ce9fb96a1ede798df2022f58157409f789f1
parentbb468eab3064d1e8bec5d6c6f53c60ccce2c9dc2 (diff)
downloadotp-ca368c8503712dce0044201bf25323ace3372a62.tar.gz
otp-ca368c8503712dce0044201bf25323ace3372a62.tar.bz2
otp-ca368c8503712dce0044201bf25323ace3372a62.zip
v3_codegen: Correct code generation for an error/1 call in a guard
Sometimes v3_codegen would generate unsafe code when there was a call to error/1 in a guard.
-rw-r--r--lib/compiler/src/v3_codegen.erl8
-rw-r--r--lib/compiler/test/guard_SUITE.erl8
2 files changed, 10 insertions, 6 deletions
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index f531056591..45403338b4 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -1155,19 +1155,15 @@ call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
%% Inside a guard. The only allowed function call is to
%% erlang:error/1,2. We will generate the following code:
%%
- %% jump FailureLabel
%% move {atom,ok} DestReg
- %%
- %% The 'move' instruction will never be executed, but we
- %% generate it anyway in case the beam_validator is run
- %% on unoptimized code.
+ %% jump FailureLabel
{remote,{atom,erlang},{atom,error}} = Func, %Assertion.
[{var,DestVar}] = Rs,
Int0 = clear_dead(Bef, Le#l.i, Vdb),
Reg = put_reg(DestVar, Int0#sr.reg),
Int = Int0#sr{reg=Reg},
Dst = fetch_reg(DestVar, Reg),
- {[{jump,{f,Fail}},{move,{atom,ok},Dst}],
+ {[{move,{atom,ok},Dst},{jump,{f,Fail}}],
clear_dead(Int, Le#l.i, Vdb),St0};
#cg{} ->
%% Ordinary function call in a function body.
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 83298e546e..6302f82f29 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1835,6 +1835,8 @@ bad_guards(Config) when is_list(Config) ->
fc(catch bad_guards_3(not_a_map, [x])),
fc(catch bad_guards_3(42, [x])),
+ fc(catch bad_guards_4()),
+
ok.
%% beam_bool used to produce GC BIF instructions whose
@@ -1852,6 +1854,12 @@ bad_guards_2(M, [_]) when M#{a := 0, b => 0}, map_size(M) ->
bad_guards_3(M, [_]) when is_map(M) andalso M#{a := 0, b => 0}, length(M) ->
ok.
+%% v3_codegen would generate a jump to the failure label, but
+%% without initializing x(0). The code at the failure label expected
+%% x(0) to be initialized.
+
+bad_guards_4() when not (error#{}); {not 0.0} -> freedom.
+
%% Building maps in a guard in a 'catch' would crash v3_codegen.
guard_in_catch(_Config) ->