"func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 *any)\n"
"func @\"\".mapiternext (@\"\".hiter·1 *any)\n"
"func @\"\".makechan (@\"\".chanType·2 *byte, @\"\".hint·3 int64) (@\"\".hchan·1 chan any)\n"
- "func @\"\".chanrecv1 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any) (@\"\".elem·1 any)\n"
- "func @\"\".chanrecv2 (@\"\".chanType·3 *byte, @\"\".hchan·4 <-chan any) (@\"\".elem·1 any, @\"\".received·2 bool)\n"
- "func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 any)\n"
+ "func @\"\".chanrecv1 (@\"\".chanType·1 *byte, @\"\".hchan·2 <-chan any, @\"\".elem·3 *any)\n"
+ "func @\"\".chanrecv2 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (? bool)\n"
+ "func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 *any)\n"
"func @\"\".closechan (@\"\".hchan·1 any)\n"
- "func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 any) (? bool)\n"
+ "func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n"
"func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n"
"func @\"\".selectnbrecv2 (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".received·4 *bool, @\"\".hchan·5 <-chan any) (? bool)\n"
"func @\"\".newselect (@\"\".size·2 int32) (@\"\".sel·1 *byte)\n"
// *byte is really *runtime.Type
func makechan(chanType *byte, hint int64) (hchan chan any)
-func chanrecv1(chanType *byte, hchan <-chan any) (elem any)
-func chanrecv2(chanType *byte, hchan <-chan any) (elem any, received bool)
-func chansend1(chanType *byte, hchan chan<- any, elem any)
+func chanrecv1(chanType *byte, hchan <-chan any, elem *any)
+func chanrecv2(chanType *byte, hchan <-chan any, elem *any) bool
+func chansend1(chanType *byte, hchan chan<- any, elem *any)
func closechan(hchan any)
-func selectnbsend(chanType *byte, hchan chan<- any, elem any) bool
+func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool
func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool
func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool
case OSEND:
// if c != nil && selectnbsend(c, v) { body } else { default body }
ch = cheapexpr(n->left, &r->ninit);
+ a = n->right;
+ a = assignconv(a, ch->type->type, "select chan send");
+ walkexpr(&a, &r->ninit);
+ if(islvalue(a)) {
+ a = nod(OADDR, a, N);
+ } else {
+ var = temp(a->type);
+ tmp = nod(OAS, var, a);
+ typecheck(&tmp, Etop);
+ r->ninit = list(r->ninit, tmp);
+ a = nod(OADDR, var, N);
+ }
r->ntest = mkcall1(chanfn("selectnbsend", 2, ch->type),
- types[TBOOL], &r->ninit, typename(ch->type), ch, n->right);
+ types[TBOOL], &r->ninit, typename(ch->type), ch, a);
break;
case OSELRECV:
case OCALLFUNC:
case ODELETE:
case OSEND:
- case ORECV:
case OPRINT:
case OPRINTN:
case OPANIC:
n->op = OEMPTY; // don't leave plain values as statements.
break;
+ case ORECV:
+ // special case for a receive where we throw away
+ // the value received.
+ if(n->typecheck == 0)
+ fatal("missing typecheck: %+N", n);
+ init = n->ninit;
+ n->ninit = nil;
+
+ walkexpr(&n->left, &init);
+ n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, &init, typename(n->left->type), n->left, nodnil());
+ walkexpr(&n, &init);
+
+ addinit(&n, init);
+ break;
+
case OBREAK:
case ODCL:
case OCONTINUE:
goto ret;
case OAS2:
+ as2:
*init = concat(*init, n->ninit);
n->ninit = nil;
walkexprlistsafe(n->list, init);
goto ret;
case OAS2FUNC:
- as2func:
// a,b,... = fn()
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
+ var = temp(r->left->type->type);
+ n1 = nod(OADDR, var, N);
fn = chanfn("chanrecv2", 2, r->left->type);
- r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left);
- n->rlist->n = r;
- n->op = OAS2FUNC;
- goto as2func;
+ r = mkcall1(fn, types[TBOOL], init, typename(r->left->type), r->left, n1);
+ n->op = OAS2;
+ n->rlist = concat(list1(var), list1(r));
+ goto as2;
case OAS2MAPR:
// a,b = m[i];
case ORECV:
walkexpr(&n->left, init);
- walkexpr(&n->right, init);
- n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, typename(n->left->type), n->left);
+ var = temp(n->left->type->type);
+ n1 = nod(OADDR, var, N);
+ n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1);
+ walkexpr(&n, init);
+ *init = list(*init, n);
+ n = var;
goto ret;
case OSLICE:
goto ret;
case OSEND:
- n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n->right);
+ n1 = n->right;
+ n1 = assignconv(n1, n->left->type->type, "chan send");
+ walkexpr(&n1, init);
+ if(islvalue(n1)) {
+ n1 = nod(OADDR, n1, N);
+ } else {
+ var = temp(n1->type);
+ n1 = nod(OAS, var, n1);
+ typecheck(&n1, Etop);
+ *init = list(*init, n1);
+ n1 = nod(OADDR, var, N);
+ }
+ n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1);
goto ret;
case OCLOSURE:
runtime·blockevent(mysg.releasetime - t0, 2);
}
-// chansend1(hchan *chan any, elem any);
+// chansend1(hchan *chan any, elem *any);
#pragma textflag NOSPLIT
void
-runtime·chansend1(ChanType *t, Hchan* c, ...)
+runtime·chansend1(ChanType *t, Hchan* c, byte *v)
{
- runtime·chansend(t, c, (byte*)(&c+1), nil, runtime·getcallerpc(&t));
+ runtime·chansend(t, c, v, nil, runtime·getcallerpc(&t));
}
-// chanrecv1(hchan *chan any) (elem any);
+// chanrecv1(hchan *chan any, elem *any);
#pragma textflag NOSPLIT
void
-runtime·chanrecv1(ChanType *t, Hchan* c, ...)
+runtime·chanrecv1(ChanType *t, Hchan* c, byte *v)
{
- runtime·chanrecv(t, c, (byte*)(&c+1), nil, nil);
+ runtime·chanrecv(t, c, v, nil, nil);
}
-// chanrecv2(hchan *chan any) (elem any, received bool);
+// chanrecv2(hchan *chan any, elem *any) (received bool);
#pragma textflag NOSPLIT
void
-runtime·chanrecv2(ChanType *t, Hchan* c, ...)
+runtime·chanrecv2(ChanType *t, Hchan* c, byte *v, bool received)
{
- byte *ae, *ap;
-
- ae = (byte*)(&c+1);
- ap = ae + t->elem->size;
- runtime·chanrecv(t, c, ae, nil, ap);
+ runtime·chanrecv(t, c, v, nil, &received);
}
-// func selectnbsend(c chan any, elem any) bool
+// func selectnbsend(c chan any, elem *any) bool
//
// compiler implements
//
//
#pragma textflag NOSPLIT
void
-runtime·selectnbsend(ChanType *t, Hchan *c, ...)
+runtime·selectnbsend(ChanType *t, Hchan *c, byte *val, bool pres)
{
- byte *ae, *ap;
-
- ae = (byte*)(&c + 1);
- ap = ae + ROUND(t->elem->size, Structrnd);
- runtime·chansend(t, c, ae, ap, runtime·getcallerpc(&t));
+ runtime·chansend(t, c, val, &pres, runtime·getcallerpc(&t));
}
// func selectnbrecv(elem *any, c chan any) bool
runtime·chanrecv(t, c, val, sp, &received);
}
-static void newselect(int32, Select**);
+static Select* newselect(int32);
// newselect(size uint32) (sel *byte);
#pragma textflag NOSPLIT
void
-runtime·newselect(int32 size, ...)
+runtime·newselect(int32 size, byte *sel)
{
- int32 o;
- Select **selp;
-
- o = ROUND(sizeof(size), Structrnd);
- selp = (Select**)((byte*)&size + o);
- newselect(size, selp);
+ sel = (byte*)newselect(size);
+ FLUSH(&sel);
}
-static void
-newselect(int32 size, Select **selp)
+static Select*
+newselect(int32 size)
{
int32 n;
Select *sel;
sel->ncase = 0;
sel->lockorder = (void*)(sel->scase + size);
sel->pollorder = (void*)(sel->lockorder + size);
- *selp = sel;
if(debug)
runtime·printf("newselect s=%p size=%d\n", sel, size);
+ return sel;
}
// cut in half to give stack a chance to split
rcase = (runtimeSelect*)cases.array;
- newselect(cases.len, &sel);
+ sel = newselect(cases.len);
for(i=0; i<cases.len; i++) {
rc = &rcase[i];
switch(rc->dir) {