compile, runtime: make selectnbrecv return two values
The only different between selectnbrecv and selectnbrecv2 is the later set the input pointer value by second return value from chanrecv. So by making selectnbrecv return two values from chanrecv, we can get rid of selectnbrecv2, the compiler can now call only selectnbrecv and generate simpler code. This is the gofrontend version of https://golang.org/cl/292890. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/339529
This commit is contained in:
parent
cbbd439a33
commit
e435e72ad7
4 changed files with 35 additions and 61 deletions
|
@ -1,4 +1,4 @@
|
|||
54361805bd611d896042b879ee7f6d2d4d088537
|
||||
2031f0be9c0b5fda6421d290a0261eb6bd1c8205
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
|
|
@ -204,12 +204,8 @@ DEF_GO_RUNTIME(SELECTNBSEND, "runtime.selectnbsend", P2(CHAN, POINTER), R1(BOOL)
|
|||
|
||||
// Non-blocking receive a value from a channel, used for two-case select
|
||||
// statement with a default case.
|
||||
DEF_GO_RUNTIME(SELECTNBRECV, "runtime.selectnbrecv", P2(POINTER, CHAN), R1(BOOL))
|
||||
|
||||
// Non-blocking tuple receive from a channel, used for two-case select
|
||||
// statement with a default case.
|
||||
DEF_GO_RUNTIME(SELECTNBRECV2, "runtime.selectnbrecv2", P3(POINTER, POINTER, CHAN),
|
||||
R1(BOOL))
|
||||
DEF_GO_RUNTIME(SELECTNBRECV, "runtime.selectnbrecv", P2(POINTER, CHAN),
|
||||
R2(BOOL, BOOL))
|
||||
|
||||
// Block execution. Used for zero-case select.
|
||||
DEF_GO_RUNTIME(BLOCK, "runtime.block", P0(), R0())
|
||||
|
|
|
@ -6051,7 +6051,7 @@ Select_statement::lower_two_case(Block* b)
|
|||
Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
|
||||
|
||||
Block* bchan;
|
||||
Expression* call;
|
||||
Expression* cond;
|
||||
if (chancase.is_send())
|
||||
{
|
||||
// if selectnbsend(chan, &val) { body } else { default body }
|
||||
|
@ -6065,7 +6065,7 @@ Select_statement::lower_two_case(Block* b)
|
|||
|
||||
Expression* ref = Expression::make_temporary_reference(ts, loc);
|
||||
Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
|
||||
call = Runtime::make_call(Runtime::SELECTNBSEND, loc, 2, chanref, addr);
|
||||
cond = Runtime::make_call(Runtime::SELECTNBSEND, loc, 2, chanref, addr);
|
||||
bchan = chancase.statements();
|
||||
}
|
||||
else
|
||||
|
@ -6075,34 +6075,31 @@ Select_statement::lower_two_case(Block* b)
|
|||
|
||||
Expression* ref = Expression::make_temporary_reference(ts, loc);
|
||||
Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
|
||||
Expression* okref = NULL;
|
||||
if (chancase.closed() == NULL && chancase.closedvar() == NULL)
|
||||
{
|
||||
// Simple receive.
|
||||
// if selectnbrecv(&lhs, chan) { body } else { default body }
|
||||
call = Runtime::make_call(Runtime::SELECTNBRECV, loc, 2, addr, chanref);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tuple receive.
|
||||
// if selectnbrecv2(&lhs, &ok, chan) { body } else { default body }
|
||||
|
||||
Type* booltype = Type::make_boolean_type();
|
||||
Temporary_statement* okts = Statement::make_temporary(booltype, NULL,
|
||||
loc);
|
||||
b->add_statement(okts);
|
||||
// selected, ok = selectnbrecv(&lhs, chan)
|
||||
Call_expression* call = Runtime::make_call(Runtime::SELECTNBRECV, loc, 2,
|
||||
addr, chanref);
|
||||
|
||||
okref = Expression::make_temporary_reference(okts, loc);
|
||||
Expression* okaddr = Expression::make_unary(OPERATOR_AND, okref, loc);
|
||||
call = Runtime::make_call(Runtime::SELECTNBRECV2, loc, 3, addr, okaddr,
|
||||
chanref);
|
||||
}
|
||||
Temporary_statement* selected_temp =
|
||||
Statement::make_temporary(Type::make_boolean_type(),
|
||||
Expression::make_call_result(call, 0),
|
||||
loc);
|
||||
b->add_statement(selected_temp);
|
||||
|
||||
Temporary_statement* ok_temp =
|
||||
Statement::make_temporary(Type::make_boolean_type(),
|
||||
Expression::make_call_result(call, 1),
|
||||
loc);
|
||||
b->add_statement(ok_temp);
|
||||
|
||||
cond = Expression::make_temporary_reference(selected_temp, loc);
|
||||
|
||||
Location cloc = chancase.location();
|
||||
bchan = new Block(b, loc);
|
||||
if (chancase.val() != NULL && !chancase.val()->is_sink_expression())
|
||||
{
|
||||
Statement* as = Statement::make_assignment(chancase.val(), ref->copy(),
|
||||
Statement* as = Statement::make_assignment(chancase.val(),
|
||||
ref->copy(),
|
||||
cloc);
|
||||
bchan->add_statement(as);
|
||||
}
|
||||
|
@ -6114,12 +6111,18 @@ Select_statement::lower_two_case(Block* b)
|
|||
|
||||
if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression())
|
||||
{
|
||||
Expression* okref = Expression::make_temporary_reference(ok_temp,
|
||||
cloc);
|
||||
Statement* as = Statement::make_assignment(chancase.closed(),
|
||||
okref->copy(), cloc);
|
||||
okref, cloc);
|
||||
bchan->add_statement(as);
|
||||
}
|
||||
else if (chancase.closedvar() != NULL)
|
||||
chancase.closedvar()->var_value()->set_init(okref->copy());
|
||||
{
|
||||
Expression* okref = Expression::make_temporary_reference(ok_temp,
|
||||
cloc);
|
||||
chancase.closedvar()->var_value()->set_init(okref);
|
||||
}
|
||||
|
||||
Statement* bs = Statement::make_block_statement(chancase.statements(),
|
||||
cloc);
|
||||
|
@ -6127,7 +6130,7 @@ Select_statement::lower_two_case(Block* b)
|
|||
}
|
||||
|
||||
Statement* ifs =
|
||||
Statement::make_if_statement(call, bchan, defcase.statements(), loc);
|
||||
Statement::make_if_statement(cond, bchan, defcase.statements(), loc);
|
||||
b->add_statement(ifs);
|
||||
|
||||
Statement* label =
|
||||
|
|
|
@ -33,7 +33,6 @@ import (
|
|||
//go:linkname closechan
|
||||
//go:linkname selectnbsend
|
||||
//go:linkname selectnbrecv
|
||||
//go:linkname selectnbrecv2
|
||||
|
||||
const (
|
||||
maxAlign = 8
|
||||
|
@ -709,28 +708,6 @@ func selectnbsend(c *hchan, elem unsafe.Pointer) (selected bool) {
|
|||
return chansend(c, elem, false, getcallerpc())
|
||||
}
|
||||
|
||||
// compiler implements
|
||||
//
|
||||
// select {
|
||||
// case v = <-c:
|
||||
// ... foo
|
||||
// default:
|
||||
// ... bar
|
||||
// }
|
||||
//
|
||||
// as
|
||||
//
|
||||
// if selectnbrecv(&v, c) {
|
||||
// ... foo
|
||||
// } else {
|
||||
// ... bar
|
||||
// }
|
||||
//
|
||||
func selectnbrecv(elem unsafe.Pointer, c *hchan) (selected bool) {
|
||||
selected, _ = chanrecv(c, elem, false)
|
||||
return
|
||||
}
|
||||
|
||||
// compiler implements
|
||||
//
|
||||
// select {
|
||||
|
@ -742,16 +719,14 @@ func selectnbrecv(elem unsafe.Pointer, c *hchan) (selected bool) {
|
|||
//
|
||||
// as
|
||||
//
|
||||
// if c != nil && selectnbrecv2(&v, &ok, c) {
|
||||
// if selected, ok = selectnbrecv(&v, c); selected {
|
||||
// ... foo
|
||||
// } else {
|
||||
// ... bar
|
||||
// }
|
||||
//
|
||||
func selectnbrecv2(elem unsafe.Pointer, received *bool, c *hchan) (selected bool) {
|
||||
// TODO(khr): just return 2 values from this function, now that it is in Go.
|
||||
selected, *received = chanrecv(c, elem, false)
|
||||
return
|
||||
func selectnbrecv(elem unsafe.Pointer, c *hchan) (selected, received bool) {
|
||||
return chanrecv(c, elem, false)
|
||||
}
|
||||
|
||||
//go:linkname reflect_chansend reflect.chansend
|
||||
|
|
Loading…
Add table
Reference in a new issue