summaryrefslogtreecommitdiff
path: root/lib/compiler/src/beam_kernel_to_ssa.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src/beam_kernel_to_ssa.erl')
-rw-r--r--lib/compiler/src/beam_kernel_to_ssa.erl197
1 files changed, 42 insertions, 155 deletions
diff --git a/lib/compiler/src/beam_kernel_to_ssa.erl b/lib/compiler/src/beam_kernel_to_ssa.erl
index aa66d4c418..7270be7066 100644
--- a/lib/compiler/src/beam_kernel_to_ssa.erl
+++ b/lib/compiler/src/beam_kernel_to_ssa.erl
@@ -25,8 +25,8 @@
-export([module/2]).
-import(lists, [all/2,append/1,flatmap/2,foldl/3,
- keysort/2,mapfoldl/3,map/2,member/2,
- reverse/1,reverse/2,sort/1]).
+ keysort/2,mapfoldl/3,member/2,
+ reverse/1,sort/1]).
-include("v3_kernel.hrl").
-include("beam_ssa.hrl").
@@ -1048,167 +1048,54 @@ put_cg_map(LineAnno, Op, SrcMap, Dst, List, St0) ->
%%%
cg_binary(Dst, Segs0, FailCtx, Le, St0) ->
- {PutCode0,SzCalc0,St1} = cg_bin_put(Segs0, FailCtx, St0),
+ Segs1 = cg_bin_segments(Segs0, St0),
+ Segs = case Segs1 of
+ [#b_literal{val=binary},UnitFlags,Val,#b_literal{val=all}|Segs2] ->
+ Op = case member(single_use, Le) of
+ true -> private_append;
+ false -> append
+ end,
+ [#b_literal{val=Op},UnitFlags,Val,#b_literal{val=all}|Segs2];
+ _ ->
+ Segs1
+ end,
LineAnno = line_anno(Le),
- Anno = Le,
- case PutCode0 of
- [#b_set{op=bs_put,dst=Bin,args=[_,_,Src,#b_literal{val=all}|_]},
- #b_set{op={succeeded,_},dst=Bool,args=[Bin]},
- #b_br{bool=Bool},
- {label,_}|_] ->
- #k_bin_seg{unit=Unit0,next=Segs} = Segs0,
- Unit = #b_literal{val=Unit0},
- {PutCode,SzCalc1,St2} = cg_bin_put(Segs, FailCtx, St1),
- {_,SzVar,SzCode0,St3} = cg_size_calc(1, SzCalc1, FailCtx, St2),
- SzCode = cg_bin_anno(SzCode0, LineAnno),
- Args = case member(single_use, Anno) of
- true ->
- [#b_literal{val=private_append},Src,SzVar,Unit];
- false ->
- [#b_literal{val=append},Src,SzVar,Unit]
- end,
- BsInit = #b_set{anno=LineAnno,op=bs_init,dst=Dst,args=Args},
- {TestIs,St} = make_succeeded(Dst, FailCtx, St3),
- {SzCode ++ [BsInit] ++ TestIs ++ PutCode,St};
- [#b_set{op=bs_put}|_] ->
- {Unit,SzVar,SzCode0,St2} = cg_size_calc(8, SzCalc0, FailCtx, St1),
- SzCode = cg_bin_anno(SzCode0, LineAnno),
- Args = [#b_literal{val=new},SzVar,Unit],
- BsInit = #b_set{anno=LineAnno,op=bs_init,dst=Dst,args=Args},
- {TestIs,St} = make_succeeded(Dst, FailCtx, St2),
- {SzCode ++ [BsInit] ++ TestIs ++ PutCode0,St}
- end.
-
-cg_bin_anno([Set|Sets], Anno) ->
- [Set#b_set{anno=Anno}|Sets];
-cg_bin_anno([], _) -> [].
-
-%% cg_size_calc(PreferredUnit, SzCalc, FailCtx, St0) ->
-%% {ActualUnit,SizeVariable,SizeCode,St}.
-%% Generate size calculation code.
-
-cg_size_calc(Unit, error, _FailCtx, St) ->
- {#b_literal{val=Unit},#b_literal{val=badarg},[],St};
-cg_size_calc(8, [{1,_}|_]=SzCalc, FailCtx, St) ->
- cg_size_calc(1, SzCalc, FailCtx, St);
-cg_size_calc(8, SzCalc, FailCtx, St0) ->
- {Var,Pre,St} = cg_size_calc_1(SzCalc, FailCtx, St0),
- {#b_literal{val=8},Var,Pre,St};
-cg_size_calc(1, SzCalc0, FailCtx, St0) ->
- SzCalc = map(fun({8,#b_literal{val=Size}}) ->
- {1,#b_literal{val=8*Size}};
- ({8,{{bif,byte_size},Src}}) ->
- {1,{{bif,bit_size},Src}};
- ({8,{_,_}=UtfCalc}) ->
- {1,{'*',#b_literal{val=8},UtfCalc}};
- ({_,_}=Pair) ->
- Pair
- end, SzCalc0),
- {Var,Pre,St} = cg_size_calc_1(SzCalc, FailCtx, St0),
- {#b_literal{val=1},Var,Pre,St}.
-
-cg_size_calc_1(SzCalc, FailCtx, St0) ->
- cg_size_calc_2(SzCalc, #b_literal{val=0}, FailCtx, St0).
-
-cg_size_calc_2([{_,{'*',Unit,{_,_}=Bif}}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {BifDst,Pre1,St2} = cg_size_bif(Bif, FailCtx, St1),
- {Sum,Pre2,St} = cg_size_add(Sum1, BifDst, Unit, FailCtx, St2),
- {Sum,Pre0++Pre1++Pre2,St};
-cg_size_calc_2([{_,#b_literal{}=Sz}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {Sum,Pre,St} = cg_size_add(Sum1, Sz, #b_literal{val=1}, FailCtx, St1),
- {Sum,Pre0++Pre,St};
-cg_size_calc_2([{_,#b_var{}=Sz}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {Sum,Pre,St} = cg_size_add(Sum1, Sz, #b_literal{val=1}, FailCtx, St1),
- {Sum,Pre0++Pre,St};
-cg_size_calc_2([{_,{_,_}=Bif}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {BifDst,Pre1,St2} = cg_size_bif(Bif, FailCtx, St1),
- {Sum,Pre2,St} = cg_size_add(Sum1, BifDst, #b_literal{val=1}, FailCtx, St2),
- {Sum,Pre0++Pre1++Pre2,St};
-cg_size_calc_2([], Sum, _FailCtx, St) ->
- {Sum,[],St}.
-
-cg_size_bif(#b_var{}=Var, _FailCtx, St) ->
- {Var,[],St};
-cg_size_bif({Name,Src}, FailCtx, St0) ->
- {Dst,St1} = new_ssa_var('@ssa_bif', St0),
- Bif = #b_set{op=Name,dst=Dst,args=[Src]},
- {TestIs,St} = make_succeeded(Dst, FailCtx, St1),
- {Dst,[Bif|TestIs],St}.
-
-cg_size_add(#b_literal{val=0}, Val, #b_literal{val=1}, _FailCtx, St) ->
- {Val,[],St};
-cg_size_add(#b_literal{val=A}, #b_literal{val=B}, #b_literal{val=U}, _FailCtx, St) ->
- {#b_literal{val=A+B*U},[],St};
-cg_size_add(A, B, Unit, FailCtx, St0) ->
- {Dst,St1} = new_ssa_var('@ssa_sum', St0),
- {TestIs,St} = make_succeeded(Dst, FailCtx, St1),
- BsAdd = #b_set{op=bs_add,dst=Dst,args=[A,B,Unit]},
- {Dst,[BsAdd|TestIs],St}.
-
-cg_bin_put(Seg, FailCtx, St) ->
- cg_bin_put_1(Seg, FailCtx, [], [], St).
-
-cg_bin_put_1(#k_bin_seg{size=Size0,unit=U,type=T,flags=Fs,seg=Src0,next=Next},
- FailCtx, Acc, SzCalcAcc, St0) ->
- [Src,Size] = ssa_args([Src0,Size0], St0),
- NeedSize = bs_need_size(T),
- TypeArg = #b_literal{val=T},
- Flags = #b_literal{val=Fs},
- Unit = #b_literal{val=U},
- Args = case NeedSize of
- true -> [TypeArg,Flags,Src,Size,Unit];
- false -> [TypeArg,Flags,Src]
+ Build = #b_set{anno=LineAnno,op=bs_create_bin,args=Segs,dst=Dst},
+ {TestIs,St} = make_succeeded(Dst, FailCtx, St0),
+ {[Build|TestIs],St}.
+
+cg_bin_segments(#k_bin_seg{anno=Anno,type=Type,flags=Flags0,seg=Src0,size=Size0,unit=U,next=Next}, St) ->
+ Seg = case lists:keyfind(segment, 1,Anno) of
+ false -> [];
+ {segment,_}=Seg0 -> [Seg0]
+ end,
+ [Src,Size] = ssa_args([Src0,Size0], St),
+ TypeArg = #b_literal{val=Type},
+ Unit = case U of
+ undefined -> 0;
+ _ -> U
end,
- {Dst,St1} = new_ssa_var('@ssa_bs_put', St0),
- {TestIs,St} = make_succeeded(Dst, FailCtx, St1),
- Is = [#b_set{op=bs_put,dst=Dst,args=Args}|TestIs],
- SzCalc = bin_size_calc(T, Src, Size, U),
- cg_bin_put_1(Next, FailCtx, reverse(Is, Acc), [SzCalc|SzCalcAcc], St);
-cg_bin_put_1(#k_bin_end{}, _, Acc, SzCalcAcc, St) ->
- SzCalc = fold_size_calc(SzCalcAcc, 0, []),
- {reverse(Acc),SzCalc,St}.
+ Flags = strip_bs_construct_flags(Flags0),
+ UnitFlags = #b_literal{val=[Unit|Flags++Seg]},
+ [TypeArg,UnitFlags,Src,Size|cg_bin_segments(Next, St)];
+cg_bin_segments(#k_bin_end{}, _St) -> [].
bs_need_size(utf8) -> false;
bs_need_size(utf16) -> false;
bs_need_size(utf32) -> false;
bs_need_size(_) -> true.
-bin_size_calc(utf8, Src, _Size, _Unit) ->
- {8,{bs_utf8_size,Src}};
-bin_size_calc(utf16, Src, _Size, _Unit) ->
- {8,{bs_utf16_size,Src}};
-bin_size_calc(utf32, _Src, _Size, _Unit) ->
- {8,#b_literal{val=4}};
-bin_size_calc(binary, Src, #b_literal{val=all}, Unit) ->
- case Unit rem 8 of
- 0 -> {8,{{bif,byte_size},Src}};
- _ -> {1,{{bif,bit_size},Src}}
- end;
-bin_size_calc(_Type, _Src, Size, Unit) ->
- {Unit,Size}.
-
-fold_size_calc([{Unit,#b_literal{val=Size}}|T], Bits, Acc) ->
- if
- is_integer(Size) ->
- fold_size_calc(T, Bits + Unit*Size, Acc);
- true ->
- error
- end;
-fold_size_calc([{U,#b_var{}}=H|T], Bits, Acc) when U =:= 1; U =:= 8 ->
- fold_size_calc(T, Bits, [H|Acc]);
-fold_size_calc([{U,#b_var{}=Var}|T], Bits, Acc) ->
- fold_size_calc(T, Bits, [{1,{'*',#b_literal{val=U},Var}}|Acc]);
-fold_size_calc([{_,_}=H|T], Bits, Acc) ->
- fold_size_calc(T, Bits, [H|Acc]);
-fold_size_calc([], Bits, Acc) ->
- Bytes = Bits div 8,
- RemBits = Bits rem 8,
- Sizes = sort([{1,#b_literal{val=RemBits}},{8,#b_literal{val=Bytes}}|Acc]),
- [Pair || {_,Sz}=Pair <- Sizes, Sz =/= #b_literal{val=0}].
+%% Only keep the flags that have a meaning for binary construction and
+%% are distinct from the default value.
+strip_bs_construct_flags(Flags) ->
+ [Flag || Flag <- Flags,
+ case Flag of
+ little -> true;
+ native -> true;
+ big -> false;
+ signed -> false;
+ unsigned -> false
+ end].
%%%
%%% Utilities for creating the SSA types.