summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2019-10-24 08:58:10 +0200
committerBjörn Gustavsson <bjorn@erlang.org>2020-02-06 11:53:09 +0100
commit97301113e1df466e1a47693e72150efe8b51bcef (patch)
tree2c8de3fc9ad3a1c922af515b831fc7560177b0f2
parent82645f41a29b9af18cddac0b338dd2c856eb09a1 (diff)
downloaderlang-97301113e1df466e1a47693e72150efe8b51bcef.tar.gz
Remove handling of #c_receive{} and #k_receive{}
Remove handling of the `receive` Core Erlang in compiler passes. For the moment, at least, we will keep the similar code in the `cerl` modules, because there could be tools other than the compiler that could use those modules.
-rw-r--r--lib/compiler/src/beam_kernel_to_ssa.erl61
-rw-r--r--lib/compiler/src/core_lib.erl2
-rw-r--r--lib/compiler/src/sys_core_fold.erl26
-rw-r--r--lib/compiler/src/v3_kernel.erl72
-rw-r--r--lib/compiler/src/v3_kernel.hrl3
-rw-r--r--lib/compiler/src/v3_kernel_pp.erl18
6 files changed, 8 insertions, 174 deletions
diff --git a/lib/compiler/src/beam_kernel_to_ssa.erl b/lib/compiler/src/beam_kernel_to_ssa.erl
index 1741bd806a..6b2da2fda3 100644
--- a/lib/compiler/src/beam_kernel_to_ssa.erl
+++ b/lib/compiler/src/beam_kernel_to_ssa.erl
@@ -123,14 +123,6 @@ cg(#k_try_enter{arg=Ta,vars=Vs,body=Tb,evars=Evs,handler=Th}, St) ->
try_enter_cg(Ta, Vs, Tb, Evs, Th, St);
cg(#k_catch{body=Cb,ret=[R]}, St) ->
do_catch_cg(Cb, R, St);
-cg(#k_receive{anno=Le,timeout=Te,var=Rvar,body=Rm,action=Tes,ret=Rs}, St) ->
- recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, St);
-cg(#k_receive_next{}, #cg{recv=Recv}=St) ->
- Is = [#b_set{op=recv_next},make_uncond_branch(Recv)],
- {Is,St};
-cg(#k_receive_accept{}, St) ->
- Remove = #b_set{op=remove_message},
- {[Remove],St};
cg(#k_put{anno=Le,arg=Con,ret=Var}, St) ->
put_cg(Var, Con, Le, St);
cg(#k_return{args=[Ret0]}, St) ->
@@ -797,59 +789,6 @@ bif_is_record_cg(Dst, Tuple, TagVal, ArityVal, St0) ->
Is = Is0 ++ [GetArity] ++ Is1 ++ [GetTag] ++ Is2 ++ Is3,
{Is,St}.
-%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
-%% [Ret], Le, St) -> {[Ainstr],St}.
-
-recv_loop_cg(Te, _Rvar, #k_receive_next{}, Tes, Rs, _Le, St0) ->
- {Tl,St1} = new_label(St0),
- {Bl,St2} = new_label(St1),
- St3 = St2#cg{break=Bl,recv=Tl},
- {Wis,St4} = cg_recv_wait(Te, Tes, St3),
- {BreakVars,St} = new_ssa_vars(Rs, St4),
- {[make_uncond_branch(Tl),{label,Tl}] ++ Wis ++
- [{label,Bl},#cg_phi{vars=BreakVars}],
- St#cg{break=St0#cg.break,recv=St0#cg.recv}};
-recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, St0) ->
- %% Get labels.
- {Rl,St1} = new_label(St0),
- {Tl,St2} = new_label(St1),
- {Bl,St3} = new_label(St2),
- St4 = St3#cg{break=Bl,recv=Rl},
- {Ris,St5} = cg_recv_mesg(Rvar, Rm, Tl, Le, St4),
- {Wis,St6} = cg_recv_wait(Te, Tes, St5),
- {BreakVars,St} = new_ssa_vars(Rs, St6),
- {Ris ++ [{label,Tl}] ++ Wis ++
- [{label,Bl},#cg_phi{vars=BreakVars}],
- St#cg{break=St0#cg.break,recv=St0#cg.recv}}.
-
-%% cg_recv_mesg( ) -> {[Ainstr],St}.
-
-cg_recv_mesg(#k_var{name=R}, Rm, Tl, Le, St0) ->
- {Dst,St1} = new_ssa_var(R, St0),
- {Mis,St2} = match_cg(Rm, none, St1),
- RecvLbl = St1#cg.recv,
- {TestIs,St} = make_succeeded(Dst, {guard, Tl}, St2),
- Is = [#b_br{anno=line_anno(Le),bool=#b_literal{val=true},
- succ=RecvLbl,fail=RecvLbl},
- {label,RecvLbl},
- #b_set{op=peek_message,dst=Dst}|TestIs],
- {Is++Mis,St}.
-
-%% cg_recv_wait(Te, Tes, St) -> {[Ainstr],St}.
-
-cg_recv_wait(#k_literal{val=0}, Es, St0) ->
- {Tis,St} = cg(Es, St0),
- {[#b_set{op=timeout}|Tis],St};
-cg_recv_wait(Te, Es, St0) ->
- {Tis,St1} = cg(Es, St0),
- Args = [ssa_arg(Te, St1)],
- {WaitDst,St2} = new_ssa_var('@ssa_wait', St1),
- {WaitIs,St} = make_succeeded(WaitDst, {guard, St1#cg.recv}, St2),
- %% Infinite timeout will be optimized later.
- Is = [#b_set{op=wait_timeout,dst=WaitDst,args=Args}] ++ WaitIs ++
- [#b_set{op=timeout}] ++ Tis,
- {Is,St}.
-
%% try_cg(TryBlock, [BodyVar], TryBody, [ExcpVar], TryHandler, [Ret], St) ->
%% {[Ainstr],St}.
diff --git a/lib/compiler/src/core_lib.erl b/lib/compiler/src/core_lib.erl
index c1806272bd..8073ed603c 100644
--- a/lib/compiler/src/core_lib.erl
+++ b/lib/compiler/src/core_lib.erl
@@ -79,8 +79,6 @@ vu_expr(V, #c_seq{arg=Arg,body=B}) ->
vu_expr(V, Arg) orelse vu_expr(V, B);
vu_expr(V, #c_case{arg=Arg,clauses=Cs}) ->
vu_expr(V, Arg) orelse vu_clauses(V, Cs);
-vu_expr(V, #c_receive{clauses=Cs,timeout=T,action=A}) ->
- vu_clauses(V, Cs) orelse vu_expr(V, T) orelse vu_expr(V, A);
vu_expr(V, #c_apply{op=Op,args=As}) ->
vu_expr_list(V, [Op|As]);
vu_expr(V, #c_call{module=M,name=N,args=As}) ->
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 05a42348b7..47fb2cc1bf 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -392,11 +392,6 @@ expr(#c_case{}=Case0, Ctxt, Sub) ->
Other ->
expr(Other, Ctxt, Sub)
end;
-expr(#c_receive{anno=Anno,clauses=Cs0,timeout=T0,action=A0}=Recv, Ctxt, Sub) ->
- Cs1 = clauses(#c_var{name='_'}, Cs0, Ctxt, Sub, false, Anno),
- T1 = expr(T0, value, Sub),
- A1 = body(A0, Ctxt, Sub),
- Recv#c_receive{clauses=Cs1,timeout=T1,action=A1};
expr(#c_apply{anno=Anno,op=Op0,args=As0}=Apply0, _, Sub) ->
Op1 = expr(Op0, value, Sub),
As1 = expr_list(As0, value, Sub),
@@ -541,10 +536,6 @@ ifes_1(FVar, #c_map_pair{key=Key,val=Val}, _Safe) ->
ifes_1(FVar, Key, false) andalso ifes_1(FVar, Val, false);
ifes_1(FVar, #c_primop{args=Args}, _Safe) ->
ifes_list(FVar, Args, false);
-ifes_1(FVar, #c_receive{timeout=Timeout,action=Action,clauses=Clauses}, Safe) ->
- ifes_1(FVar, Timeout, false) andalso
- ifes_1(FVar, Action, Safe) andalso
- ifes_list(FVar, Clauses, Safe);
ifes_1(FVar, #c_seq{arg=Arg,body=Body}, Safe) ->
%% Arg of a #c_seq{} has no effect so it's okay to use FVar there even if
%% Safe=false.
@@ -1095,10 +1086,6 @@ clause_1(#c_clause{guard=G0,body=B0}=Cl, Ps1, Cexpr, Ctxt, Sub1) ->
%% No need for substitution tricks when the guard
%% does not contain any variables.
Sub1;
- {#c_var{name='_'},_,_} ->
- %% In a 'receive', Cexpr is the variable '_', which represents the
- %% message being matched. We must NOT do any extra substiutions.
- Sub1;
{#c_var{},[#c_var{}=Var],_} ->
%% The idea here is to optimize expressions such as
%%
@@ -2603,19 +2590,6 @@ delay_build_expr_1(#c_case{clauses=Cs0}=Case, TypeSig) ->
delay_build_expr_1(#c_let{body=B0}=Let, TypeSig) ->
B = delay_build_expr(B0, TypeSig),
Let#c_let{body=B};
-delay_build_expr_1(#c_receive{clauses=Cs0,
- timeout=Timeout,
- action=A0}=Rec, TypeSig) ->
- Cs = delay_build_cs(Cs0, TypeSig),
- A = case {Timeout,A0} of
- {#c_literal{val=infinity},#c_literal{}} ->
- {_Type,Arity} = TypeSig,
- Es = lists:duplicate(Arity, A0),
- core_lib:make_values(Es);
- _ ->
- delay_build_expr(A0, TypeSig)
- end,
- Rec#c_receive{clauses=Cs,action=A};
delay_build_expr_1(#c_seq{body=B0}=Seq, TypeSig) ->
B = delay_build_expr(B0, TypeSig),
Seq#c_seq{body=B};
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 650065f7ee..095455975f 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -82,7 +82,7 @@
keyfind/3,keyreplace/4,
last/1,partition/2,reverse/1,
sort/1,sort/2,splitwith/2]).
--import(ordsets, [add_element/2,del_element/2,intersection/2,
+-import(ordsets, [add_element/2,intersection/2,
subtract/2,union/2,union/1]).
-include("core_parse.hrl").
@@ -105,8 +105,6 @@ copy_anno(Kdst, Ksrc) ->
-record(iletrec, {anno=[],defs}).
-record(ialias, {anno=[],vars,pat}).
-record(iclause, {anno=[],isub,osub,pats,guard,body}).
--record(ireceive_accept, {anno=[],arg}).
--record(ireceive_next, {anno=[],arg}).
-type warning() :: term(). % XXX: REFINE
@@ -184,8 +182,6 @@ body(#c_values{anno=A,es=Ces}, Sub, St0) ->
%% Do this here even if only in bodies.
{Kes,Pe,St1} = atomic_list(Ces, Sub, St0),
{#ivalues{anno=A,args=Kes},Pe,St1};
-body(#ireceive_next{anno=A}, _, St) ->
- {#k_receive_next{anno=A},[],St};
body(Ce, Sub, St0) ->
expr(Ce, Sub, St0).
@@ -326,22 +322,6 @@ expr(#c_case{arg=Ca,clauses=Ccs}, Sub, St0) ->
{Km,St3} = kmatch(Kvs, Ccs, Sub, St2),
Match = flatten_seq(build_match(Km)),
{last(Match),Pa ++ Pv ++ droplast(Match),St3};
-expr(#c_receive{anno=A,clauses=Ccs0,timeout=Ce,action=Ca}, Sub, St0) ->
- {Ke,Pe,St1} = atomic(Ce, Sub, St0), %Force this to be atomic!
- {Rvar,St2} = new_var(St1),
- %% Need to massage accept clauses and add reject clause before matching.
- Ccs1 = map(fun (#c_clause{anno=Banno,body=B0}=C) ->
- B1 = #c_seq{arg=#ireceive_accept{anno=A},body=B0},
- C#c_clause{anno=Banno,body=B1}
- end, Ccs0),
- {Mpat,St3} = new_var_name(St2),
- Rc = #c_clause{anno=[compiler_generated|A],
- pats=[#c_var{name=Mpat}],guard=#c_literal{anno=A,val=true},
- body=#ireceive_next{anno=A}},
- {Km,St4} = kmatch([Rvar], Ccs1 ++ [Rc], Sub, add_var_def(Rvar, St3)),
- {Ka,Pa,St5} = body(Ca, Sub, St4),
- {#k_receive{anno=A,var=Rvar,body=Km,timeout=Ke,action=pre_seq(Pa, Ka)},
- Pe,St5};
expr(#c_apply{anno=A,op=Cop,args=Cargs}, Sub, St) ->
c_apply(A, Cop, Cargs, Sub, St);
expr(#c_call{anno=A,module=M0,name=F0,args=Cargs}, Sub, St0) ->
@@ -382,9 +362,7 @@ expr(#c_try{anno=A,arg=Ca,vars=Cvs,body=Cb,evars=Evs,handler=Ch}, Sub0, St0) ->
evars=Kevs,handler=pre_seq(Ph, Kh)},[],St5};
expr(#c_catch{anno=A,body=Cb}, Sub, St0) ->
{Kb,Pb,St1} = body(Cb, Sub, St0),
- {#k_catch{anno=A,body=pre_seq(Pb, Kb)},[],St1};
-%% Handle internal expressions.
-expr(#ireceive_accept{anno=A}, _Sub, St) -> {#k_receive_accept{anno=A},[],St}.
+ {#k_catch{anno=A,body=pre_seq(Pb, Kb)},[],St1}.
%% Implement letrec in the traditional way as a local
%% function for each definition in the letrec.
@@ -950,9 +928,6 @@ new_vars(0, St, Vs) -> {Vs,St}.
make_vars(Vs) -> [ #k_var{name=V} || V <- Vs ].
-add_var_def(V, St) ->
- St#kern{ds=cerl_sets:add_element(V#k_var.name, St#kern.ds)}.
-
%% is_remote_bif(Mod, Name, Arity) -> true | false.
%% Test if function is really a BIF.
@@ -1843,24 +1818,13 @@ ubody(E, return, St0) ->
ubody(pre_seq(Pa, #ivalues{args=[Ea]}), return, St1)
end;
ubody(E, {break,[_]} = Break, St0) ->
- %%ok = io:fwrite("ubody ~w:~p~n", [?LINE,{E,Br}]),
- %% Exiting expressions need no trailing break.
- case is_exit_expr(E) of
- true -> uexpr(E, return, St0);
- false ->
- {Ea,Pa,St1} = force_atomic(E, St0),
- ubody(pre_seq(Pa, #ivalues{args=[Ea]}), Break, St1)
- end;
+ {Ea,Pa,St1} = force_atomic(E, St0),
+ ubody(pre_seq(Pa, #ivalues{args=[Ea]}), Break, St1);
ubody(E, {break,Rs}=Break, St0) ->
- case is_exit_expr(E) of
- true ->
- uexpr(E, return, St0);
- false ->
- {Vs,St1} = new_vars(length(Rs), St0),
- Iset = #iset{vars=Vs,arg=E},
- PreSeq = pre_seq([Iset], #ivalues{args=Vs}),
- ubody(PreSeq, Break, St1)
- end.
+ {Vs,St1} = new_vars(length(Rs), St0),
+ Iset = #iset{vars=Vs,arg=E},
+ PreSeq = pre_seq([Iset], #ivalues{args=Vs}),
+ ubody(PreSeq, Break, St1).
iletrec_funs(#iletrec{defs=Fs}, St0) ->
%% Use union of all free variables.
@@ -1893,12 +1857,6 @@ iletrec_funs_gen(Fs, FreeVs, St) ->
end, St, Fs).
-%% is_exit_expr(Kexpr) -> boolean().
-%% Test whether Kexpr always exits and never returns.
-
-is_exit_expr(#k_receive_next{}) -> true;
-is_exit_expr(_) -> false.
-
%% is_enter_expr(Kexpr) -> boolean().
%% Test whether Kexpr is "enterable", i.e. can handle return from
%% within itself without extra #k_return{}.
@@ -1906,8 +1864,6 @@ is_exit_expr(_) -> false.
is_enter_expr(#k_try{}) -> true;
is_enter_expr(#k_call{}) -> true;
is_enter_expr(#k_match{}) -> true;
-is_enter_expr(#k_receive{}) -> true;
-is_enter_expr(#k_receive_next{}) -> true;
is_enter_expr(#k_letrec_goto{}) -> true;
is_enter_expr(_) -> false.
@@ -1953,18 +1909,6 @@ uexpr(#k_match{anno=A,body=B0}, Br, St0) ->
Rs = break_rets(Br),
{B1,Bu,St1} = umatch(B0, Br, St0),
{#k_match{anno=A,body=B1,ret=Rs},Bu,St1};
-uexpr(#k_receive{anno=A,var=V,body=B0,timeout=T,action=A0}, Br, St0) ->
- Rs = break_rets(Br),
- Tu = lit_vars(T), %Timeout is atomic
- {B1,Bu,St1} = umatch(B0, Br, St0),
- {A1,Au,St2} = ubody(A0, Br, St1),
- Used = del_element(V#k_var.name, union(Bu, union(Tu, Au))),
- {#k_receive{anno=A,var=V,body=B1,timeout=T,action=A1,ret=Rs},
- Used,St2};
-uexpr(#k_receive_accept{anno=A}, _, St) ->
- {#k_receive_accept{anno=A},[],St};
-uexpr(#k_receive_next{anno=A}, _, St) ->
- {#k_receive_next{anno=A},[],St};
uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
{break,Rs0}=Br, St0) ->
case {Vs,B0,H0,Rs0} of
diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl
index e8336a8f26..582e4f9b12 100644
--- a/lib/compiler/src/v3_kernel.hrl
+++ b/lib/compiler/src/v3_kernel.hrl
@@ -52,9 +52,6 @@
-record(k_test, {anno=[],op,args}).
-record(k_call, {anno=[],op,args,ret=[]}).
-record(k_enter, {anno=[],op,args}).
--record(k_receive, {anno=[],var,body,timeout,action,ret=[]}).
--record(k_receive_accept, {anno=[]}).
--record(k_receive_next, {anno=[]}).
-record(k_try, {anno=[],arg,vars,body,evars,handler,ret=[]}).
-record(k_try_enter, {anno=[],arg,vars,body,evars,handler}).
-record(k_catch, {anno=[],body,ret=[]}).
diff --git a/lib/compiler/src/v3_kernel_pp.erl b/lib/compiler/src/v3_kernel_pp.erl
index aeddd13472..f7479e6b15 100644
--- a/lib/compiler/src/v3_kernel_pp.erl
+++ b/lib/compiler/src/v3_kernel_pp.erl
@@ -289,24 +289,6 @@ format_1(#k_catch{body=B,ret=Rs}, Ctxt) ->
"end",
format_ret(Rs, Ctxt1)
];
-format_1(#k_receive{var=V,body=B,timeout=T,action=A,ret=Rs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
- ["receive ",
- format(V, Ctxt),
- nl_indent(Ctxt1),
- format(B, Ctxt1),
- nl_indent(Ctxt),
- "after ",
- format(T, ctxt_bump_indent(Ctxt, 6)),
- " ->",
- nl_indent(Ctxt1),
- format(A, Ctxt1),
- nl_indent(Ctxt),
- "end",
- format_ret(Rs, Ctxt1)
- ];
-format_1(#k_receive_accept{}, _Ctxt) -> "receive_accept";
-format_1(#k_receive_next{}, _Ctxt) -> "receive_next";
format_1(#k_break{args=As}, Ctxt) ->
["<",
format_hseq(As, ",", ctxt_bump_indent(Ctxt, 1), fun format/2),