2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// select
|
2015-02-13 14:40:36 -05:00
|
|
|
func typecheckselect(sel *Node) {
|
|
|
|
var ncase *Node
|
|
|
|
var n *Node
|
2015-02-23 16:07:24 -05:00
|
|
|
|
2015-03-02 14:22:05 -05:00
|
|
|
var def *Node
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := setlineno(sel)
|
2015-02-23 16:07:24 -05:00
|
|
|
count := 0
|
2016-03-08 10:26:20 -08:00
|
|
|
typechecklist(sel.Ninit.Slice(), Etop)
|
2016-03-04 16:13:17 -08:00
|
|
|
for it := nodeSeqIterate(sel.List); !it.Done(); it.Next() {
|
2015-02-13 14:40:36 -05:00
|
|
|
count++
|
2016-03-04 16:13:17 -08:00
|
|
|
ncase = it.N()
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(ncase)
|
|
|
|
if ncase.Op != OXCASE {
|
2016-03-07 08:23:55 -08:00
|
|
|
Fatalf("typecheckselect %v", Oconv(ncase.Op, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2016-03-04 16:13:17 -08:00
|
|
|
if nodeSeqLen(ncase.List) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
// default
|
|
|
|
if def != nil {
|
|
|
|
Yyerror("multiple defaults in select (first at %v)", def.Line())
|
|
|
|
} else {
|
|
|
|
def = ncase
|
|
|
|
}
|
2016-03-04 16:13:17 -08:00
|
|
|
} else if nodeSeqLen(ncase.List) > 1 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("select cases cannot be lists")
|
|
|
|
} else {
|
2016-03-04 16:13:17 -08:00
|
|
|
it2 := nodeSeqIterate(ncase.List)
|
|
|
|
n = typecheck(it2.P(), Etop)
|
2015-02-13 14:40:36 -05:00
|
|
|
ncase.Left = n
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&ncase.List, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(n)
|
|
|
|
switch n.Op {
|
|
|
|
default:
|
|
|
|
Yyerror("select case must be receive, send or assign recv")
|
|
|
|
|
|
|
|
// convert x = <-c into OSELRECV(x, <-c).
|
|
|
|
// remove implicit conversions; the eventual assignment
|
|
|
|
// will reintroduce them.
|
|
|
|
case OAS:
|
2015-03-06 21:18:41 +11:00
|
|
|
if (n.Right.Op == OCONVNOP || n.Right.Op == OCONVIFACE) && n.Right.Implicit {
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Right = n.Right.Left
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.Right.Op != ORECV {
|
|
|
|
Yyerror("select assignment must have receive on right hand side")
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Op = OSELRECV
|
|
|
|
|
|
|
|
// convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok
|
|
|
|
case OAS2RECV:
|
2016-03-04 16:13:17 -08:00
|
|
|
if nodeSeqFirst(n.Rlist).Op != ORECV {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("select assignment must have receive on right hand side")
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Op = OSELRECV2
|
2016-03-04 16:13:17 -08:00
|
|
|
n.Left = nodeSeqFirst(n.List)
|
|
|
|
setNodeSeq(&n.List, []*Node{nodeSeqSecond(n.List)})
|
|
|
|
n.Right = nodeSeqFirst(n.Rlist)
|
|
|
|
setNodeSeq(&n.Rlist, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// convert <-c into OSELRECV(N, <-c)
|
|
|
|
case ORECV:
|
|
|
|
n = Nod(OSELRECV, nil, n)
|
|
|
|
|
|
|
|
n.Typecheck = 1
|
|
|
|
ncase.Left = n
|
|
|
|
|
|
|
|
case OSEND:
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-08 10:26:20 -08:00
|
|
|
typechecklist(ncase.Nbody.Slice(), Etop)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
sel.Xoffset = int64(count)
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func walkselect(sel *Node) {
|
2016-03-04 16:13:17 -08:00
|
|
|
if nodeSeqLen(sel.List) == 0 && sel.Xoffset != 0 {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("double walkselect") // already rewrote
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := setlineno(sel)
|
2016-03-04 16:13:17 -08:00
|
|
|
i := nodeSeqLen(sel.List)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// optimization: zero-case select
|
2016-02-27 14:31:33 -08:00
|
|
|
var init []*Node
|
2015-02-23 16:07:24 -05:00
|
|
|
var r *Node
|
|
|
|
var n *Node
|
|
|
|
var var_ *Node
|
|
|
|
var selv *Node
|
|
|
|
var cas *Node
|
2015-02-13 14:40:36 -05:00
|
|
|
if i == 0 {
|
2016-02-27 14:31:33 -08:00
|
|
|
sel.Nbody.Set([]*Node{mkcall("block", nil, nil)})
|
2015-02-13 14:40:36 -05:00
|
|
|
goto out
|
|
|
|
}
|
|
|
|
|
|
|
|
// optimization: one-case select: single op.
|
2015-10-22 09:51:12 +09:00
|
|
|
// TODO(rsc): Reenable optimization once order.go can handle it.
|
2015-02-13 14:40:36 -05:00
|
|
|
// golang.org/issue/7672.
|
|
|
|
if i == 1 {
|
2016-03-04 16:13:17 -08:00
|
|
|
cas := nodeSeqFirst(sel.List)
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(cas)
|
2016-03-04 16:13:17 -08:00
|
|
|
l := nodeSeqSlice(cas.Ninit)
|
2015-02-13 14:40:36 -05:00
|
|
|
if cas.Left != nil { // not default:
|
2015-02-23 16:07:24 -05:00
|
|
|
n := cas.Left
|
2016-03-04 16:13:17 -08:00
|
|
|
l = append(l, nodeSeqSlice(n.Ninit)...)
|
|
|
|
setNodeSeq(&n.Ninit, nil)
|
2015-02-23 16:07:24 -05:00
|
|
|
var ch *Node
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
default:
|
2016-03-07 08:23:55 -08:00
|
|
|
Fatalf("select %v", Oconv(n.Op, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// ok already
|
|
|
|
case OSEND:
|
|
|
|
ch = n.Left
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OSELRECV, OSELRECV2:
|
2015-02-13 14:40:36 -05:00
|
|
|
ch = n.Right.Left
|
2016-03-04 16:13:17 -08:00
|
|
|
if n.Op == OSELRECV || nodeSeqLen(n.List) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Left == nil {
|
|
|
|
n = n.Right
|
|
|
|
} else {
|
|
|
|
n.Op = OAS
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.Left == nil {
|
|
|
|
typecheck(&nblank, Erv|Easgn)
|
|
|
|
n.Left = nblank
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Op = OAS2
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&n.List, append([]*Node{n.Left}, nodeSeqSlice(n.List)...))
|
|
|
|
setNodeSeq(&n.Rlist, []*Node{n.Right})
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Right = nil
|
|
|
|
n.Left = nil
|
|
|
|
n.Typecheck = 0
|
|
|
|
typecheck(&n, Etop)
|
|
|
|
}
|
|
|
|
|
|
|
|
// if ch == nil { block() }; n;
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OIF, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-26 21:30:20 -04:00
|
|
|
a.Left = Nod(OEQ, ch, nodnil())
|
2016-03-07 22:54:46 -08:00
|
|
|
var ln Nodes
|
|
|
|
ln.Set(l)
|
|
|
|
a.Nbody.Set([]*Node{mkcall("block", nil, &ln)})
|
|
|
|
l = ln.Slice()
|
2015-02-13 14:40:36 -05:00
|
|
|
typecheck(&a, Etop)
|
2016-03-04 16:13:17 -08:00
|
|
|
l = append(l, a)
|
|
|
|
l = append(l, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2016-03-04 16:13:17 -08:00
|
|
|
l = append(l, cas.Nbody.Slice()...)
|
|
|
|
sel.Nbody.Set(l)
|
2015-02-13 14:40:36 -05:00
|
|
|
goto out
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert case value arguments to addresses.
|
|
|
|
// this rewrite is used by both the general code and the next optimization.
|
2016-03-04 16:13:17 -08:00
|
|
|
for it := nodeSeqIterate(sel.List); !it.Done(); it.Next() {
|
|
|
|
cas = it.N()
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(cas)
|
|
|
|
n = cas.Left
|
|
|
|
if n == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
switch n.Op {
|
|
|
|
case OSEND:
|
|
|
|
n.Right = Nod(OADDR, n.Right, nil)
|
|
|
|
typecheck(&n.Right, Erv)
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OSELRECV, OSELRECV2:
|
2016-03-04 16:13:17 -08:00
|
|
|
if n.Op == OSELRECV2 && nodeSeqLen(n.List) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Op = OSELRECV
|
|
|
|
}
|
|
|
|
if n.Op == OSELRECV2 {
|
2016-03-04 16:13:17 -08:00
|
|
|
it := nodeSeqIterate(n.List)
|
|
|
|
*it.P() = Nod(OADDR, it.N(), nil)
|
|
|
|
typecheck(it.P(), Erv)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if n.Left == nil {
|
|
|
|
n.Left = nodnil()
|
|
|
|
} else {
|
|
|
|
n.Left = Nod(OADDR, n.Left, nil)
|
|
|
|
typecheck(&n.Left, Erv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// optimization: two-case select but one is default: single non-blocking op.
|
2016-03-04 16:13:17 -08:00
|
|
|
if i == 2 && (nodeSeqFirst(sel.List).Left == nil || nodeSeqSecond(sel.List).Left == nil) {
|
2015-02-23 16:07:24 -05:00
|
|
|
var cas *Node
|
|
|
|
var dflt *Node
|
2016-03-04 16:13:17 -08:00
|
|
|
if nodeSeqFirst(sel.List).Left == nil {
|
|
|
|
cas = nodeSeqSecond(sel.List)
|
|
|
|
dflt = nodeSeqFirst(sel.List)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2016-03-04 16:13:17 -08:00
|
|
|
dflt = nodeSeqSecond(sel.List)
|
2016-03-08 10:26:20 -08:00
|
|
|
cas = nodeSeqFirst(sel.List.Slice())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
n := cas.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(n)
|
2015-02-23 16:07:24 -05:00
|
|
|
r := Nod(OIF, nil, nil)
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&r.Ninit, cas.Ninit)
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
default:
|
2016-03-07 08:23:55 -08:00
|
|
|
Fatalf("select %v", Oconv(n.Op, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// if selectnbsend(c, v) { body } else { default body }
|
|
|
|
case OSEND:
|
2015-02-23 16:07:24 -05:00
|
|
|
ch := n.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-26 21:30:20 -04:00
|
|
|
r.Left = mkcall1(chanfn("selectnbsend", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), ch, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// if c != nil && selectnbrecv(&v, c) { body } else { default body }
|
|
|
|
case OSELRECV:
|
|
|
|
r = Nod(OIF, nil, nil)
|
|
|
|
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&r.Ninit, cas.Ninit)
|
2015-02-23 16:07:24 -05:00
|
|
|
ch := n.Right.Left
|
2015-05-26 21:30:20 -04:00
|
|
|
r.Left = mkcall1(chanfn("selectnbrecv", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, ch)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// if c != nil && selectnbrecv2(&v, c) { body } else { default body }
|
|
|
|
case OSELRECV2:
|
|
|
|
r = Nod(OIF, nil, nil)
|
|
|
|
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&r.Ninit, cas.Ninit)
|
2015-02-23 16:07:24 -05:00
|
|
|
ch := n.Right.Left
|
2016-03-07 09:36:24 -08:00
|
|
|
r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, nodeSeqFirst(n.List), ch)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-05-26 21:30:20 -04:00
|
|
|
typecheck(&r.Left, Erv)
|
2016-02-27 14:31:33 -08:00
|
|
|
r.Nbody.Set(cas.Nbody.Slice())
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&r.Rlist, append(nodeSeqSlice(dflt.Ninit), dflt.Nbody.Slice()...))
|
2016-02-27 14:31:33 -08:00
|
|
|
sel.Nbody.Set([]*Node{r})
|
2015-02-13 14:40:36 -05:00
|
|
|
goto out
|
|
|
|
}
|
|
|
|
|
2016-03-04 16:13:17 -08:00
|
|
|
init = nodeSeqSlice(sel.Ninit)
|
|
|
|
setNodeSeq(&sel.Ninit, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// generate sel-struct
|
|
|
|
setlineno(sel)
|
|
|
|
|
|
|
|
selv = temp(selecttype(int32(sel.Xoffset)))
|
|
|
|
r = Nod(OAS, selv, nil)
|
|
|
|
typecheck(&r, Etop)
|
2016-02-27 14:31:33 -08:00
|
|
|
init = append(init, r)
|
2015-02-13 14:40:36 -05:00
|
|
|
var_ = conv(conv(Nod(OADDR, selv, nil), Types[TUNSAFEPTR]), Ptrto(Types[TUINT8]))
|
|
|
|
r = mkcall("newselect", nil, nil, var_, Nodintconst(selv.Type.Width), Nodintconst(sel.Xoffset))
|
|
|
|
typecheck(&r, Etop)
|
2016-02-27 14:31:33 -08:00
|
|
|
init = append(init, r)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// register cases
|
2016-03-04 16:13:17 -08:00
|
|
|
for it := nodeSeqIterate(sel.List); !it.Done(); it.Next() {
|
|
|
|
cas = it.N()
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(cas)
|
|
|
|
n = cas.Left
|
|
|
|
r = Nod(OIF, nil, nil)
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&r.Ninit, cas.Ninit)
|
|
|
|
setNodeSeq(&cas.Ninit, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
if n != nil {
|
2016-03-04 16:13:17 -08:00
|
|
|
appendNodeSeq(&r.Ninit, n.Ninit)
|
|
|
|
setNodeSeq(&n.Ninit, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if n == nil {
|
|
|
|
// selectdefault(sel *byte);
|
2015-05-26 21:30:20 -04:00
|
|
|
r.Left = mkcall("selectdefault", Types[TBOOL], &r.Ninit, var_)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
|
|
|
switch n.Op {
|
|
|
|
default:
|
2016-03-07 08:23:55 -08:00
|
|
|
Fatalf("select %v", Oconv(n.Op, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
|
|
|
|
case OSEND:
|
2015-05-26 21:30:20 -04:00
|
|
|
r.Left = mkcall1(chanfn("selectsend", 2, n.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
|
|
|
case OSELRECV:
|
2015-05-26 21:30:20 -04:00
|
|
|
r.Left = mkcall1(chanfn("selectrecv", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
|
|
|
|
case OSELRECV2:
|
2016-03-04 16:13:17 -08:00
|
|
|
r.Left = mkcall1(chanfn("selectrecv2", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left, nodeSeqFirst(n.List))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// selv is no longer alive after use.
|
2016-02-27 14:31:33 -08:00
|
|
|
r.Nbody.Append(Nod(OVARKILL, selv, nil))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
r.Nbody.AppendNodes(&cas.Nbody)
|
2016-02-27 14:31:33 -08:00
|
|
|
r.Nbody.Append(Nod(OBREAK, nil, nil))
|
|
|
|
init = append(init, r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// run the select
|
|
|
|
setlineno(sel)
|
|
|
|
|
2016-02-27 14:31:33 -08:00
|
|
|
init = append(init, mkcall("selectgo", nil, nil, var_))
|
|
|
|
sel.Nbody.Set(init)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
out:
|
2016-03-04 16:13:17 -08:00
|
|
|
setNodeSeq(&sel.List, nil)
|
2016-03-07 22:54:46 -08:00
|
|
|
walkstmtlist(sel.Nbody.Slice())
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2016-02-23 07:46:01 +00:00
|
|
|
// Keep in sync with src/runtime/runtime2.go and src/runtime/select.go.
|
2015-02-13 14:40:36 -05:00
|
|
|
func selecttype(size int32) *Type {
|
2016-02-23 07:46:01 +00:00
|
|
|
// TODO(dvyukov): it's possible to generate SudoG and Scase only once
|
|
|
|
// and then cache; and also cache Select per size.
|
|
|
|
sudog := Nod(OTSTRUCT, nil, nil)
|
|
|
|
|
2016-03-04 16:13:17 -08:00
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("g")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("selectdone")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("next")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("prev")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("elem")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64])))
|
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("nrelease")), typenod(Types[TINT32])))
|
|
|
|
appendNodeSeqNode(&sudog.List, Nod(ODCLFIELD, newname(Lookup("waitlink")), typenod(Ptrto(Types[TUINT8]))))
|
2016-02-23 07:46:01 +00:00
|
|
|
typecheck(&sudog, Etype)
|
|
|
|
sudog.Type.Noalg = true
|
|
|
|
sudog.Type.Local = true
|
|
|
|
|
|
|
|
scase := Nod(OTSTRUCT, nil, nil)
|
2016-03-04 16:13:17 -08:00
|
|
|
appendNodeSeqNode(&scase.List, Nod(ODCLFIELD, newname(Lookup("elem")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&scase.List, Nod(ODCLFIELD, newname(Lookup("chan")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&scase.List, Nod(ODCLFIELD, newname(Lookup("pc")), typenod(Types[TUINTPTR])))
|
|
|
|
appendNodeSeqNode(&scase.List, Nod(ODCLFIELD, newname(Lookup("kind")), typenod(Types[TUINT16])))
|
|
|
|
appendNodeSeqNode(&scase.List, Nod(ODCLFIELD, newname(Lookup("so")), typenod(Types[TUINT16])))
|
|
|
|
appendNodeSeqNode(&scase.List, Nod(ODCLFIELD, newname(Lookup("receivedp")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&scase.List, Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64])))
|
2016-02-23 07:46:01 +00:00
|
|
|
typecheck(&scase, Etype)
|
|
|
|
scase.Type.Noalg = true
|
|
|
|
scase.Type.Local = true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
sel := Nod(OTSTRUCT, nil, nil)
|
2016-03-04 16:13:17 -08:00
|
|
|
appendNodeSeqNode(&sel.List, Nod(ODCLFIELD, newname(Lookup("tcase")), typenod(Types[TUINT16])))
|
|
|
|
appendNodeSeqNode(&sel.List, Nod(ODCLFIELD, newname(Lookup("ncase")), typenod(Types[TUINT16])))
|
|
|
|
appendNodeSeqNode(&sel.List, Nod(ODCLFIELD, newname(Lookup("pollorder")), typenod(Ptrto(Types[TUINT8]))))
|
|
|
|
appendNodeSeqNode(&sel.List, Nod(ODCLFIELD, newname(Lookup("lockorder")), typenod(Ptrto(Types[TUINT8]))))
|
2015-02-23 16:07:24 -05:00
|
|
|
arr := Nod(OTARRAY, Nodintconst(int64(size)), scase)
|
2016-03-04 16:13:17 -08:00
|
|
|
appendNodeSeqNode(&sel.List, Nod(ODCLFIELD, newname(Lookup("scase")), arr))
|
2015-02-13 14:40:36 -05:00
|
|
|
arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Ptrto(Types[TUINT8])))
|
2016-03-04 16:13:17 -08:00
|
|
|
appendNodeSeqNode(&sel.List, Nod(ODCLFIELD, newname(Lookup("lockorderarr")), arr))
|
2015-02-13 14:40:36 -05:00
|
|
|
arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Types[TUINT16]))
|
2016-03-04 16:13:17 -08:00
|
|
|
appendNodeSeqNode(&sel.List, Nod(ODCLFIELD, newname(Lookup("pollorderarr")), arr))
|
2015-02-13 14:40:36 -05:00
|
|
|
typecheck(&sel, Etype)
|
2015-09-08 03:51:30 +02:00
|
|
|
sel.Type.Noalg = true
|
2015-03-10 09:58:01 +11:00
|
|
|
sel.Type.Local = true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
return sel.Type
|
|
|
|
}
|