| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * select | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	lno := int(setlineno(sel)) | 
					
						
							|  |  |  | 	count := 0 | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 	typechecklist(sel.Ninit, Etop) | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	for l := sel.List; l != nil; l = l.Next { | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 		count++ | 
					
						
							|  |  |  | 		ncase = l.N | 
					
						
							|  |  |  | 		setlineno(ncase) | 
					
						
							|  |  |  | 		if ncase.Op != OXCASE { | 
					
						
							|  |  |  | 			Fatal("typecheckselect %v", Oconv(int(ncase.Op), 0)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ncase.List == nil { | 
					
						
							|  |  |  | 			// default | 
					
						
							|  |  |  | 			if def != nil { | 
					
						
							|  |  |  | 				Yyerror("multiple defaults in select (first at %v)", def.Line()) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				def = ncase | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if ncase.List.Next != nil { | 
					
						
							|  |  |  | 			Yyerror("select cases cannot be lists") | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			n = typecheck(&ncase.List.N, Etop) | 
					
						
							|  |  |  | 			ncase.Left = n | 
					
						
							|  |  |  | 			ncase.List = nil | 
					
						
							|  |  |  | 			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: | 
					
						
							|  |  |  | 				if n.Rlist.N.Op != ORECV { | 
					
						
							|  |  |  | 					Yyerror("select assignment must have receive on right hand side") | 
					
						
							|  |  |  | 					break | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				n.Op = OSELRECV2 | 
					
						
							|  |  |  | 				n.Left = n.List.N | 
					
						
							|  |  |  | 				n.Ntest = n.List.Next.N | 
					
						
							|  |  |  | 				n.List = nil | 
					
						
							|  |  |  | 				n.Right = n.Rlist.N | 
					
						
							|  |  |  | 				n.Rlist = nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// convert <-c into OSELRECV(N, <-c) | 
					
						
							|  |  |  | 			case ORECV: | 
					
						
							|  |  |  | 				n = Nod(OSELRECV, nil, n) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				n.Typecheck = 1 | 
					
						
							|  |  |  | 				ncase.Left = n | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case OSEND: | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		typechecklist(ncase.Nbody, Etop) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sel.Xoffset = int64(count) | 
					
						
							|  |  |  | 	lineno = int32(lno) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func walkselect(sel *Node) { | 
					
						
							|  |  |  | 	if sel.List == nil && sel.Xoffset != 0 { | 
					
						
							|  |  |  | 		Fatal("double walkselect") // already rewrote | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	lno := int(setlineno(sel)) | 
					
						
							|  |  |  | 	i := count(sel.List) | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// optimization: zero-case select | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	var init *NodeList | 
					
						
							|  |  |  | 	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 { | 
					
						
							|  |  |  | 		sel.Nbody = list1(mkcall("block", nil, nil)) | 
					
						
							|  |  |  | 		goto out | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// optimization: one-case select: single op. | 
					
						
							|  |  |  | 	// TODO(rsc): Reenable optimization once order.c can handle it. | 
					
						
							|  |  |  | 	// golang.org/issue/7672. | 
					
						
							|  |  |  | 	if i == 1 { | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 		cas := sel.List.N | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 		setlineno(cas) | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 		l := 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 | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 			l = concat(l, n.Ninit) | 
					
						
							|  |  |  | 			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: | 
					
						
							|  |  |  | 				Fatal("select %v", Oconv(int(n.Op), 0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// ok already | 
					
						
							|  |  |  | 			case OSEND: | 
					
						
							|  |  |  | 				ch = n.Left | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case OSELRECV, | 
					
						
							|  |  |  | 				OSELRECV2: | 
					
						
							|  |  |  | 				ch = n.Right.Left | 
					
						
							|  |  |  | 				if n.Op == OSELRECV || n.Ntest == nil { | 
					
						
							|  |  |  | 					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 | 
					
						
							|  |  |  | 				n.List = list(list1(n.Left), n.Ntest) | 
					
						
							|  |  |  | 				n.Rlist = list1(n.Right) | 
					
						
							|  |  |  | 				n.Right = nil | 
					
						
							|  |  |  | 				n.Left = nil | 
					
						
							|  |  |  | 				n.Ntest = 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
										 |  |  | 
 | 
					
						
							|  |  |  | 			a.Ntest = Nod(OEQ, ch, nodnil()) | 
					
						
							|  |  |  | 			a.Nbody = list1(mkcall("block", nil, &l)) | 
					
						
							|  |  |  | 			typecheck(&a, Etop) | 
					
						
							|  |  |  | 			l = list(l, a) | 
					
						
							|  |  |  | 			l = list(l, n) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		l = concat(l, cas.Nbody) | 
					
						
							|  |  |  | 		sel.Nbody = l | 
					
						
							|  |  |  | 		goto out | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// convert case value arguments to addresses. | 
					
						
							|  |  |  | 	// this rewrite is used by both the general code and the next optimization. | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	for l := sel.List; l != nil; l = l.Next { | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 		cas = l.N | 
					
						
							|  |  |  | 		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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case OSELRECV, | 
					
						
							|  |  |  | 			OSELRECV2: | 
					
						
							|  |  |  | 			if n.Op == OSELRECV2 && n.Ntest == nil { | 
					
						
							|  |  |  | 				n.Op = OSELRECV | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if n.Op == OSELRECV2 { | 
					
						
							|  |  |  | 				n.Ntest = Nod(OADDR, n.Ntest, nil) | 
					
						
							|  |  |  | 				typecheck(&n.Ntest, Erv) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			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. | 
					
						
							|  |  |  | 	if i == 2 && (sel.List.N.Left == nil || sel.List.Next.N.Left == nil) { | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 		var cas *Node | 
					
						
							|  |  |  | 		var dflt *Node | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 		if sel.List.N.Left == nil { | 
					
						
							|  |  |  | 			cas = sel.List.Next.N | 
					
						
							|  |  |  | 			dflt = sel.List.N | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			dflt = sel.List.Next.N | 
					
						
							|  |  |  | 			cas = sel.List.N | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 		r.Ninit = cas.Ninit | 
					
						
							|  |  |  | 		switch n.Op { | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			Fatal("select %v", Oconv(int(n.Op), 0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 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
										 |  |  | 
 | 
					
						
							|  |  |  | 			r.Ntest = mkcall1(chanfn("selectnbsend", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), ch, n.Right) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// if c != nil && selectnbrecv(&v, c) { body } else { default body } | 
					
						
							|  |  |  | 		case OSELRECV: | 
					
						
							|  |  |  | 			r = Nod(OIF, nil, nil) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			r.Ninit = cas.Ninit | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 			ch := n.Right.Left | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 			r.Ntest = mkcall1(chanfn("selectnbrecv", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, ch) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// if c != nil && selectnbrecv2(&v, c) { body } else { default body } | 
					
						
							|  |  |  | 		case OSELRECV2: | 
					
						
							|  |  |  | 			r = Nod(OIF, nil, nil) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			r.Ninit = cas.Ninit | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 			ch := n.Right.Left | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 			r.Ntest = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, n.Ntest, ch) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		typecheck(&r.Ntest, Erv) | 
					
						
							|  |  |  | 		r.Nbody = cas.Nbody | 
					
						
							|  |  |  | 		r.Nelse = concat(dflt.Ninit, dflt.Nbody) | 
					
						
							|  |  |  | 		sel.Nbody = list1(r) | 
					
						
							|  |  |  | 		goto out | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init = sel.Ninit | 
					
						
							|  |  |  | 	sel.Ninit = nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// generate sel-struct | 
					
						
							|  |  |  | 	setlineno(sel) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	selv = temp(selecttype(int32(sel.Xoffset))) | 
					
						
							|  |  |  | 	r = Nod(OAS, selv, nil) | 
					
						
							|  |  |  | 	typecheck(&r, Etop) | 
					
						
							|  |  |  | 	init = list(init, r) | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	init = list(init, r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// register cases | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	for l := sel.List; l != nil; l = l.Next { | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 		cas = l.N | 
					
						
							|  |  |  | 		setlineno(cas) | 
					
						
							|  |  |  | 		n = cas.Left | 
					
						
							|  |  |  | 		r = Nod(OIF, nil, nil) | 
					
						
							|  |  |  | 		r.Ninit = cas.Ninit | 
					
						
							|  |  |  | 		cas.Ninit = nil | 
					
						
							|  |  |  | 		if n != nil { | 
					
						
							|  |  |  | 			r.Ninit = concat(r.Ninit, n.Ninit) | 
					
						
							|  |  |  | 			n.Ninit = nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if n == nil { | 
					
						
							|  |  |  | 			// selectdefault(sel *byte); | 
					
						
							|  |  |  | 			r.Ntest = mkcall("selectdefault", Types[TBOOL], &r.Ninit, var_) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			switch n.Op { | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				Fatal("select %v", Oconv(int(n.Op), 0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool); | 
					
						
							|  |  |  | 			case OSEND: | 
					
						
							|  |  |  | 				r.Ntest = mkcall1(chanfn("selectsend", 2, n.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Left, n.Right) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool); | 
					
						
							|  |  |  | 			case OSELRECV: | 
					
						
							|  |  |  | 				r.Ntest = mkcall1(chanfn("selectrecv", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool); | 
					
						
							|  |  |  | 			case OSELRECV2: | 
					
						
							|  |  |  | 				r.Ntest = mkcall1(chanfn("selectrecv2", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left, n.Ntest) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// selv is no longer alive after use. | 
					
						
							|  |  |  | 		r.Nbody = list(r.Nbody, Nod(OVARKILL, selv, nil)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r.Nbody = concat(r.Nbody, cas.Nbody) | 
					
						
							|  |  |  | 		r.Nbody = list(r.Nbody, Nod(OBREAK, nil, nil)) | 
					
						
							|  |  |  | 		init = list(init, r) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// run the select | 
					
						
							|  |  |  | 	setlineno(sel) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init = list(init, mkcall("selectgo", nil, nil, var_)) | 
					
						
							|  |  |  | 	sel.Nbody = init | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	sel.List = nil | 
					
						
							|  |  |  | 	walkstmtlist(sel.Nbody) | 
					
						
							|  |  |  | 	lineno = int32(lno) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Keep in sync with src/runtime/chan.h. | 
					
						
							|  |  |  | func selecttype(size int32) *Type { | 
					
						
							|  |  |  | 	// TODO(dvyukov): it's possible to generate SudoG and Scase only once | 
					
						
							|  |  |  | 	// and then cache; and also cache Select per size. | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	sudog := Nod(OTSTRUCT, nil, nil) | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("g")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("selectdone")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("next")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("prev")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("elem")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64]))) | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("nrelease")), typenod(Types[TINT32]))) | 
					
						
							|  |  |  | 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("waitlink")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	typecheck(&sudog, Etype) | 
					
						
							|  |  |  | 	sudog.Type.Noalg = 1 | 
					
						
							|  |  |  | 	sudog.Type.Local = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	scase := Nod(OTSTRUCT, nil, nil) | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("elem")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("chan")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("pc")), typenod(Types[TUINTPTR]))) | 
					
						
							|  |  |  | 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("kind")), typenod(Types[TUINT16]))) | 
					
						
							|  |  |  | 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("so")), typenod(Types[TUINT16]))) | 
					
						
							|  |  |  | 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("receivedp")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64]))) | 
					
						
							|  |  |  | 	typecheck(&scase, Etype) | 
					
						
							|  |  |  | 	scase.Type.Noalg = 1 | 
					
						
							|  |  |  | 	scase.Type.Local = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 16:07:24 -05:00
										 |  |  | 	sel := Nod(OTSTRUCT, nil, nil) | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 	sel.List = list(sel.List, Nod(ODCLFIELD, newname(Lookup("tcase")), typenod(Types[TUINT16]))) | 
					
						
							|  |  |  | 	sel.List = list(sel.List, Nod(ODCLFIELD, newname(Lookup("ncase")), typenod(Types[TUINT16]))) | 
					
						
							|  |  |  | 	sel.List = list(sel.List, Nod(ODCLFIELD, newname(Lookup("pollorder")), typenod(Ptrto(Types[TUINT8])))) | 
					
						
							|  |  |  | 	sel.List = list(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) | 
					
						
							| 
									
										
										
										
											2015-02-13 14:40:36 -05:00
										 |  |  | 	sel.List = list(sel.List, Nod(ODCLFIELD, newname(Lookup("scase")), arr)) | 
					
						
							|  |  |  | 	arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Ptrto(Types[TUINT8]))) | 
					
						
							|  |  |  | 	sel.List = list(sel.List, Nod(ODCLFIELD, newname(Lookup("lockorderarr")), arr)) | 
					
						
							|  |  |  | 	arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Types[TUINT16])) | 
					
						
							|  |  |  | 	sel.List = list(sel.List, Nod(ODCLFIELD, newname(Lookup("pollorderarr")), arr)) | 
					
						
							|  |  |  | 	typecheck(&sel, Etype) | 
					
						
							|  |  |  | 	sel.Type.Noalg = 1 | 
					
						
							|  |  |  | 	sel.Type.Local = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sel.Type | 
					
						
							|  |  |  | } |