File 0270-beam_validator-Fix-bitstring-unit-inference.patch of Package erlang
From c94a1035bda1d12b4cd76308285774163807f1d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Tue, 2 Feb 2021 10:25:28 +0100
Subject: [PATCH] beam_validator: Fix bitstring unit inference
---
lib/compiler/src/beam_validator.erl | 19 +++++++++++++------
lib/compiler/test/bs_match_SUITE.erl | 11 +++++++++++
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index 794ba7874e..64f990dc71 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -884,13 +884,10 @@ vi({test,bs_skip_utf32,{f,Fail},[Ctx,Live,_]}, Vst) ->
vi({test,bs_get_binary2=Op,{f,Fail},Live,[Ctx,{atom,all},Unit,_],Dst}, Vst) ->
Type = #t_bitstring{size_unit=Unit},
validate_bs_get_all(Op, Fail, Ctx, Live, Unit, Type, Dst, Vst);
-vi({test,bs_get_binary2=Op,{f,Fail},Live,[Ctx,{integer,Sz},Unit,_],Dst}, Vst) ->
- Stride = Unit * Sz,
- Type = #t_bitstring{size_unit=max(1, Stride)},
+vi({test,bs_get_binary2=Op,{f,Fail},Live,[Ctx,Size,Unit,_],Dst}, Vst) ->
+ Type = #t_bitstring{size_unit=bsm_size_unit(Size, Unit)},
+ Stride = bsm_stride(Size, Unit),
validate_bs_get(Op, Fail, Ctx, Live, Stride, Type, Dst, Vst);
-vi({test,bs_get_binary2=Op,{f,Fail},Live,[Ctx,_,Unit,_],Dst}, Vst) ->
- Type = #t_bitstring{size_unit=max(1, Unit)},
- validate_bs_get(Op, Fail, Ctx, Live, Unit, Type, Dst, Vst);
vi({test,bs_get_integer2=Op,{f,Fail},Live,
[Ctx,{integer,Sz},Unit,{field_flags,Flags}],Dst},Vst) ->
@@ -1880,6 +1877,16 @@ bsm_restore(Reg, SavePoint, Vst) ->
error({illegal_restore, SavePoint, range})
end.
+bsm_stride({integer, Size}, Unit) ->
+ Size * Unit;
+bsm_stride(_Size, Unit) ->
+ Unit.
+
+bsm_size_unit({integer, Size}, Unit) ->
+ max(1, Size) * max(1, Unit);
+bsm_size_unit(_Size, Unit) ->
+ max(1, Unit).
+
validate_select_val(_Fail, _Choices, _Src, #vst{current=none}=Vst) ->
%% We've already branched on all of Src's possible values, so we know we
%% can't reach the fail label or any of the remaining choices.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 8770477ed4..eb9e0f341a 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -2404,6 +2404,9 @@ empty_matches(Config) when is_list(Config) ->
<<0,1,0,2,0,3>> = em_2(id(<<1,2,3>>)),
<<>> = em_2(id(<<>>)),
+ <<1,2,3>> = em_3(id(<<1,2,3>>)),
+ <<>> = em_3(id(<<>>)),
+
<<Zero:0/unit:1>> = id(<<>>),
0 = id(Zero),
@@ -2422,6 +2425,14 @@ em_2(Bin) ->
<<K,N>> || <<K:0,N>> <= Bin
>>.
+%% The validator didn't agree with the type optimization pass on what the unit
+%% of empty binary segments should be.
+em_3(<<V:0/binary,Rest/bits>>) ->
+ em_3_1(V),
+ Rest.
+
+em_3_1(I) -> I.
+
id(I) -> I.
expand_and_squeeze(Config) when is_list(Config) ->
--
2.26.2