summaryrefslogtreecommitdiff
path: root/lib/compiler/src/beam_ssa_codegen.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src/beam_ssa_codegen.erl')
-rw-r--r--lib/compiler/src/beam_ssa_codegen.erl113
1 files changed, 43 insertions, 70 deletions
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
index c929b65aa3..8454d02944 100644
--- a/lib/compiler/src/beam_ssa_codegen.erl
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -252,7 +252,7 @@ need_heap_blks([], H, Acc) ->
need_heap_is([#cg_alloc{words=Words}=Alloc0|Is], N, Acc) ->
Alloc = Alloc0#cg_alloc{words=add_heap_words(N, Words)},
need_heap_is(Is, #need{}, [Alloc|Acc]);
-need_heap_is([#cg_set{anno=Anno,op=bs_init}=I0|Is], N, Acc) ->
+need_heap_is([#cg_set{anno=Anno,op=bs_create_bin}=I0|Is], N, Acc) ->
Alloc = case need_heap_need(N) of
[#cg_alloc{words=Need}] -> alloc(Need);
[] -> 0
@@ -284,13 +284,11 @@ need_heap_terminator([{_,#cg_blk{is=Is,last=#cg_br{succ=L}}}|_], L, N) ->
[] ->
{[],#need{}};
[_|_]=Alloc ->
- %% If the preceding instructions are a binary construction,
- %% hoist the allocation and incorporate into the bs_init
+ %% If the preceding instruction is a bs_create_bin instruction,
+ %% hoist the allocation and incorporate into the bs_create_bin
%% instruction.
case reverse(Is) of
- [#cg_set{op=succeeded},#cg_set{op=bs_init}|_] ->
- {[],N};
- [#cg_set{op=succeeded},#cg_set{op=bs_put}|_] ->
+ [#cg_set{op=succeeded},#cg_set{op=bs_create_bin}|_] ->
{[],N};
_ ->
%% Not binary construction. Must emit an allocation
@@ -371,20 +369,16 @@ classify_heap_need(Name, _Args) ->
%% Note: Only handle operations in this function that are not handled
%% by classify_heap_need/2.
-classify_heap_need(bs_add) -> gc;
classify_heap_need(bs_get) -> gc;
classify_heap_need(bs_get_tail) -> gc;
-classify_heap_need(bs_init) -> gc;
classify_heap_need(bs_init_writable) -> gc;
classify_heap_need(bs_match_string) -> gc;
-classify_heap_need(bs_put) -> neutral;
+classify_heap_need(bs_create_bin) -> gc;
classify_heap_need(bs_get_position) -> gc;
classify_heap_need(bs_set_position) -> neutral;
classify_heap_need(bs_skip) -> gc;
classify_heap_need(bs_start_match) -> gc;
classify_heap_need(bs_test_tail) -> neutral;
-classify_heap_need(bs_utf16_size) -> neutral;
-classify_heap_need(bs_utf8_size) -> neutral;
classify_heap_need(build_stacktrace) -> gc;
classify_heap_need(call) -> gc;
classify_heap_need(catch_end) -> gc;
@@ -677,8 +671,8 @@ get_live(#cg_set{anno=#{live:=Live}}) ->
need_live_anno(Op) ->
case Op of
{bif,_} -> true;
+ bs_create_bin -> true;
bs_get -> true;
- bs_init -> true;
bs_get_position -> true;
bs_get_tail -> true;
bs_start_match -> true;
@@ -801,7 +795,7 @@ need_y_init(#cg_set{anno=#{clobbers:=Clobbers}}) -> Clobbers;
need_y_init(#cg_set{op=bs_get}) -> true;
need_y_init(#cg_set{op=bs_get_position}) -> true;
need_y_init(#cg_set{op=bs_get_tail}) -> true;
-need_y_init(#cg_set{op=bs_init}) -> true;
+need_y_init(#cg_set{op=bs_create_bin}) -> true;
need_y_init(#cg_set{op=bs_skip,args=[#b_literal{val=Type}|_]}) ->
case Type of
utf8 -> true;
@@ -1108,30 +1102,21 @@ cg_block([#cg_set{anno=Anno,op={bif,Name},dst=Dst0,args=Args0}=I|T],
Is = [{bif,Name,{f,0},Args,Dst}|Is0],
{Is,St}
end;
-cg_block([#cg_set{op=bs_init,dst=Dst0,args=Args0,anno=Anno}=I,
+cg_block([#cg_set{op=bs_create_bin,dst=Dst0,args=Args0,anno=Anno}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) ->
Fail = bif_fail(Fail0),
Line = line(Anno),
Alloc = map_get(alloc, Anno),
- [#b_literal{val=Kind}|Args1] = Args0,
Live = get_live(I),
- case Kind of
- new ->
- [Dst,Size,{integer,Unit}] = beam_args([Dst0|Args1], St),
- {[Line|cg_bs_init(Dst, Size, Alloc, Unit, Live, Fail)],St};
- private_append ->
- [Dst,Src,Bits,{integer,Unit}] = beam_args([Dst0|Args1], St),
- Flags = {field_flags,[]},
- TestHeap = {test_heap,Alloc,Live},
- BsPrivateAppend = {bs_private_append,Fail,Bits,Unit,Src,Flags,Dst},
- Is = [TestHeap,Line,BsPrivateAppend],
- {Is,St};
- append ->
- [Dst,Src,Bits,{integer,Unit}] = beam_args([Dst0|Args1], St),
- Flags = {field_flags,[]},
- Is = [Line,{bs_append,Fail,Bits,Alloc,Live,Unit,Src,Flags,Dst}],
- {Is,St}
- end;
+ [Dst|Args1] = beam_args([Dst0|Args0], St),
+ Args = bs_args(Args1),
+ Unit = case Args of
+ [{atom,append},_Seg,U|_] -> U;
+ [{atom,private_append},_Seg,U|_] -> U;
+ _ -> 1
+ end,
+ Is = [Line,{bs_create_bin,Fail,Alloc,Live,Unit,Dst,{list,Args}}],
+ {Is,St};
cg_block([#cg_set{op=bs_start_match,
dst=Ctx0,
args=[#b_literal{val=new},Bin0]}=I,
@@ -1156,10 +1141,6 @@ cg_block([#cg_set{op=bs_match_string,args=[CtxVar,#b_literal{val=String0}]},
Is = [{test,bs_match_string,Fail,[CtxReg,Bits,{string,String}]}],
{Is,St};
-cg_block([#cg_set{op=bs_put,args=Args0},
- #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
- Args = beam_args(Args0, St),
- {cg_bs_put(bif_fail(Fail), Args),St};
cg_block([#cg_set{dst=Dst0,op=landingpad,args=Args0}|T], Context, St0) ->
[Dst,{atom,Kind},Tag] = beam_args([Dst0|Args0], St0),
case Kind of
@@ -1329,6 +1310,32 @@ cg_block([], {Bool0,Fail}, St) ->
[Bool] = beam_args([Bool0], St),
{[{test,is_eq_exact,Fail,[Bool,{atom,true}]}],St}.
+bs_args([{atom,binary},{literal,[1|_]},{literal,Bs},{atom,all}|Args])
+ when bit_size(Bs) =:= 0 ->
+ bs_args(Args);
+bs_args([{atom,binary},{literal,[1|_]}=UFs,{literal,Bs},{atom,all}|Args0])
+ when is_bitstring(Bs) ->
+ Bits = bit_size(Bs),
+ Bytes = Bits div 8,
+ case Bits rem 8 of
+ 0 ->
+ [{atom,string},0,8,nil,{string,Bs},{integer,byte_size(Bs)}|bs_args(Args0)];
+ Rem ->
+ <<Binary:Bytes/bytes,Int:Rem>> = Bs,
+ Args = [{atom,binary},UFs,{literal,Binary},{atom,all},
+ {atom,integer},{literal,[1]},{integer,Int},{integer,Rem}|Args0],
+ bs_args(Args)
+ end;
+bs_args([Type,{literal,[Unit|Fs0]},Val,Size|Args]) ->
+ Segment = proplists:get_value(segment, Fs0, 0),
+ Fs1 = proplists:delete(segment, Fs0),
+ Fs = case Fs1 of
+ [] -> nil;
+ [_|_] -> {literal,Fs1}
+ end,
+ [Type,Segment,Unit,Fs,Val,Size|bs_args(Args)];
+bs_args([]) -> [].
+
cg_copy(T0, St) ->
{Copies,T} = splitwith(fun(#cg_set{op=copy}) -> true;
(_) -> false
@@ -1716,14 +1723,8 @@ cg_instr(remove_message, [], _Dst) ->
cg_instr(resume, [A,B], _Dst) ->
[{bif,raise,{f,0},[A,B],{x,0}}].
-cg_test(bs_add=Op, Fail, [Src1,Src2,{integer,Unit}], Dst, _I) ->
- [{Op,Fail,[Src1,Src2,Unit],Dst}];
cg_test(bs_skip, Fail, Args, _Dst, I) ->
cg_bs_skip(Fail, Args, I);
-cg_test(bs_utf8_size=Op, Fail, [Src], Dst, _I) ->
- [{Op,Fail,Src,Dst}];
-cg_test(bs_utf16_size=Op, Fail, [Src], Dst, _I) ->
- [{Op,Fail,Src,Dst}];
cg_test({float,convert}, Fail, [Src], Dst, #cg_set{anno=Anno}) ->
{f,0} = Fail, %Assertion.
[line(Anno),{fconv,Src,Dst}];
@@ -1793,34 +1794,6 @@ field_flags(Flags, #cg_set{anno=#{location:={File,Line}}}) ->
field_flags(Flags, _) ->
{field_flags,Flags}.
-cg_bs_put(Fail, [{atom,Type},{literal,Flags}|Args]) ->
- Op = case Type of
- integer -> bs_put_integer;
- float -> bs_put_float;
- binary -> bs_put_binary;
- utf8 -> bs_put_utf8;
- utf16 -> bs_put_utf16;
- utf32 -> bs_put_utf32
- end,
- case Args of
- [Src,Size,{integer,Unit}] ->
- [{Op,Fail,Size,Unit,{field_flags,Flags},Src}];
- [Src] ->
- [{Op,Fail,{field_flags,Flags},Src}]
- end.
-
-cg_bs_init(Dst, Size0, Alloc, Unit, Live, Fail) ->
- Op = case Unit of
- 1 -> bs_init_bits;
- 8 -> bs_init2
- end,
- Size = cg_bs_init_size(Size0),
- [{Op,Fail,Size,Alloc,Live,{field_flags,[]},Dst}].
-
-cg_bs_init_size({x,_}=R) -> R;
-cg_bs_init_size({y,_}=R) -> R;
-cg_bs_init_size({integer,Int}) -> Int.
-
cg_catch(Agg, T0, Context, St0) ->
{Moves,T1} = cg_extract(T0, Agg, St0),
{T,St} = cg_block(T1, Context, St0),