summaryrefslogtreecommitdiff
path: root/lib/compiler/src/beam_ssa_bc_size.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src/beam_ssa_bc_size.erl')
-rw-r--r--lib/compiler/src/beam_ssa_bc_size.erl47
1 files changed, 24 insertions, 23 deletions
diff --git a/lib/compiler/src/beam_ssa_bc_size.erl b/lib/compiler/src/beam_ssa_bc_size.erl
index f795641592..9646408cc9 100644
--- a/lib/compiler/src/beam_ssa_bc_size.erl
+++ b/lib/compiler/src/beam_ssa_bc_size.erl
@@ -276,32 +276,13 @@ calc_size_is([I|Is], Bs0) ->
calc_size_is(Is, Bs);
calc_size_is([], Bs) -> Bs.
-calc_size_instr(#b_set{op=bs_add,args=[A,B,U],dst=Dst}, Bs) ->
- %% We must make sure that the value of bs_add only depends on literals
- %% and arguments passed from the function that created the writable
- %% binary.
- case {get_value(A, Bs),get_arg_value(B, Bs)} of
- {#b_literal{}=Lit,Val} ->
- Bs#{Dst => {expr,{{bif,'+'},[Lit,{{bif,'*'},[Val,U]}]}}};
- {{expr,Expr},Val} ->
- Bs#{Dst => {expr,{{bif,'+'},[Expr,{{bif,'*'},[Val,U]}]}}};
- {_,_} ->
- %% The value depends on a variable of which we know nothing.
- Bs#{Dst => any}
- end;
-calc_size_instr(#b_set{op=bs_init,args=[#b_literal{val=private_append},
- Writable,Size,Unit],
+calc_size_instr(#b_set{op=bs_create_bin,
+ args=[#b_literal{val=private_append},_,Writable,_|Args],
dst=Dst}, Bs) ->
- case get_value(Size, Bs) of
- {arg,SizeOrigin} ->
- Expr = {{bif,'*'},[SizeOrigin,Unit]},
- update_writable(Dst, Writable, Expr, Bs);
- #b_literal{} ->
- Expr = {{bif,'*'},[Size,Unit]},
- update_writable(Dst, Writable, Expr, Bs);
+ case calc_create_bin_size(Args, Bs) of
{expr,Expr} ->
update_writable(Dst, Writable, Expr, Bs);
- _ ->
+ any ->
Bs#{Dst => any}
end;
calc_size_instr(#b_set{op=bs_match,args=[_Type,Ctx,_Flags,
@@ -347,6 +328,26 @@ calc_size_instr(#b_set{op={succeeded,_},args=[Arg],dst=Dst}, Bs) ->
calc_size_instr(#b_set{dst=Dst}, Bs) ->
Bs#{Dst => any}.
+calc_create_bin_size(Args, Bs) ->
+ calc_create_bin_size(Args, Bs, #b_literal{val=0}).
+
+calc_create_bin_size([_,#b_literal{val=[0|_]},_,_|_], _Bs, _Acc) ->
+ %% Construction without size (utf8/utf16/utf32).
+ any;
+calc_create_bin_size([_,#b_literal{val=[U|_]},_,Size|T], Bs, Acc0) when is_integer(U) ->
+ case get_value(Size, Bs) of
+ #b_literal{val=Val} when is_integer(Val) ->
+ Acc = {{bif,'+'},[Acc0,#b_literal{val=U*Val}]},
+ calc_create_bin_size(T, Bs, Acc);
+ {arg,Var} ->
+ Acc = {{bif,'+'},[Acc0,{{bif,'*'},[Var,#b_literal{val=U}]}]},
+ calc_create_bin_size(T, Bs, Acc);
+ _ ->
+ any
+ end;
+calc_create_bin_size([], _Bs, Acc) ->
+ {expr,Acc}.
+
update_writable(Dst, Writable, Expr, Bs) ->
case get_value(Writable, Bs) of
{writable,#b_literal{val=0}} ->