mirror of
				https://github.com/golang/go.git
				synced 2025-11-04 02:30:57 +00:00 
			
		
		
		
	cmd/compile: remove Node.Ntest, Node.Stkdelta
$ sizeof -p cmd/compile/internal/gc Node Node 272 $ Change-Id: I3d9b67eebfc0be0a4b9768d3de3dc76300abd89c Reviewed-on: https://go-review.googlesource.com/10521 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
		
							parent
							
								
									ffef180f82
								
							
						
					
					
						commit
						66be1481df
					
				
					 20 changed files with 207 additions and 269 deletions
				
			
		| 
						 | 
					@ -134,7 +134,6 @@ func (v *bottomUpVisitor) visitcode(n *Node, min uint32) uint32 {
 | 
				
			||||||
	min = v.visitcode(n.Left, min)
 | 
						min = v.visitcode(n.Left, min)
 | 
				
			||||||
	min = v.visitcode(n.Right, min)
 | 
						min = v.visitcode(n.Right, min)
 | 
				
			||||||
	min = v.visitcodelist(n.List, min)
 | 
						min = v.visitcodelist(n.List, min)
 | 
				
			||||||
	min = v.visitcode(n.Ntest, min)
 | 
					 | 
				
			||||||
	min = v.visitcodelist(n.Nbody, min)
 | 
						min = v.visitcodelist(n.Nbody, min)
 | 
				
			||||||
	min = v.visitcodelist(n.Rlist, min)
 | 
						min = v.visitcodelist(n.Rlist, min)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -543,7 +542,6 @@ func escloopdepth(e *EscState, n *Node) {
 | 
				
			||||||
	escloopdepth(e, n.Left)
 | 
						escloopdepth(e, n.Left)
 | 
				
			||||||
	escloopdepth(e, n.Right)
 | 
						escloopdepth(e, n.Right)
 | 
				
			||||||
	escloopdepthlist(e, n.List)
 | 
						escloopdepthlist(e, n.List)
 | 
				
			||||||
	escloopdepth(e, n.Ntest)
 | 
					 | 
				
			||||||
	escloopdepthlist(e, n.Nbody)
 | 
						escloopdepthlist(e, n.Nbody)
 | 
				
			||||||
	escloopdepthlist(e, n.Rlist)
 | 
						escloopdepthlist(e, n.Rlist)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -572,7 +570,7 @@ func esc(e *EscState, n *Node, up *Node) {
 | 
				
			||||||
	// process type switch as declaration.
 | 
						// process type switch as declaration.
 | 
				
			||||||
	// must happen before processing of switch body,
 | 
						// must happen before processing of switch body,
 | 
				
			||||||
	// so before recursion.
 | 
						// so before recursion.
 | 
				
			||||||
	if n.Op == OSWITCH && n.Ntest != nil && n.Ntest.Op == OTYPESW {
 | 
						if n.Op == OSWITCH && n.Left != nil && n.Left.Op == OTYPESW {
 | 
				
			||||||
		for ll := n.List; ll != nil; ll = ll.Next { // cases
 | 
							for ll := n.List; ll != nil; ll = ll.Next { // cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// ll->n->nname is the variable per case
 | 
								// ll->n->nname is the variable per case
 | 
				
			||||||
| 
						 | 
					@ -597,7 +595,6 @@ func esc(e *EscState, n *Node, up *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	esc(e, n.Left, n)
 | 
						esc(e, n.Left, n)
 | 
				
			||||||
	esc(e, n.Right, n)
 | 
						esc(e, n.Right, n)
 | 
				
			||||||
	esc(e, n.Ntest, n)
 | 
					 | 
				
			||||||
	esclist(e, n.Nbody, n)
 | 
						esclist(e, n.Nbody, n)
 | 
				
			||||||
	esclist(e, n.List, n)
 | 
						esclist(e, n.List, n)
 | 
				
			||||||
	esclist(e, n.Rlist, n)
 | 
						esclist(e, n.Rlist, n)
 | 
				
			||||||
| 
						 | 
					@ -646,12 +643,12 @@ func esc(e *EscState, n *Node, up *Node) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case OSWITCH:
 | 
						case OSWITCH:
 | 
				
			||||||
		if n.Ntest != nil && n.Ntest.Op == OTYPESW {
 | 
							if n.Left != nil && n.Left.Op == OTYPESW {
 | 
				
			||||||
			for ll := n.List; ll != nil; ll = ll.Next { // cases
 | 
								for ll := n.List; ll != nil; ll = ll.Next {
 | 
				
			||||||
 | 
									// cases
 | 
				
			||||||
				// ntest->right is the argument of the .(type),
 | 
									// ntest->right is the argument of the .(type),
 | 
				
			||||||
				// ll->n->nname is the variable per case
 | 
									// ll->n->nname is the variable per case
 | 
				
			||||||
				escassign(e, ll.N.Nname, n.Ntest.Right)
 | 
									escassign(e, ll.N.Nname, n.Left.Right)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,7 +202,6 @@ func reexportdep(n *Node) {
 | 
				
			||||||
	reexportdeplist(n.List)
 | 
						reexportdeplist(n.List)
 | 
				
			||||||
	reexportdeplist(n.Rlist)
 | 
						reexportdeplist(n.Rlist)
 | 
				
			||||||
	reexportdeplist(n.Ninit)
 | 
						reexportdeplist(n.Ninit)
 | 
				
			||||||
	reexportdep(n.Ntest)
 | 
					 | 
				
			||||||
	reexportdeplist(n.Nbody)
 | 
						reexportdeplist(n.Nbody)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -214,7 +214,7 @@ func Jconv(n *Node, flag int) string {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if c == 0 && n.Xoffset != BADWIDTH {
 | 
						if c == 0 && n.Xoffset != BADWIDTH {
 | 
				
			||||||
		fmt.Fprintf(&buf, " x(%d%+d)", n.Xoffset, n.Stkdelta)
 | 
							fmt.Fprintf(&buf, " x(%d%+d)", n.Xoffset, stkdelta[n])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if n.Class != 0 {
 | 
						if n.Class != 0 {
 | 
				
			||||||
| 
						 | 
					@ -863,9 +863,9 @@ func stmtfmt(n *Node) string {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case OIF:
 | 
						case OIF:
 | 
				
			||||||
		if simpleinit {
 | 
							if simpleinit {
 | 
				
			||||||
			f += fmt.Sprintf("if %v; %v { %v }", n.Ninit.N, n.Ntest, n.Nbody)
 | 
								f += fmt.Sprintf("if %v; %v { %v }", n.Ninit.N, n.Left, n.Nbody)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			f += fmt.Sprintf("if %v { %v }", n.Ntest, n.Nbody)
 | 
								f += fmt.Sprintf("if %v { %v }", n.Left, n.Nbody)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if n.Rlist != nil {
 | 
							if n.Rlist != nil {
 | 
				
			||||||
			f += fmt.Sprintf(" else { %v }", n.Rlist)
 | 
								f += fmt.Sprintf(" else { %v }", n.Rlist)
 | 
				
			||||||
| 
						 | 
					@ -884,8 +884,8 @@ func stmtfmt(n *Node) string {
 | 
				
			||||||
			f += " ;"
 | 
								f += " ;"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if n.Ntest != nil {
 | 
							if n.Left != nil {
 | 
				
			||||||
			f += fmt.Sprintf(" %v", n.Ntest)
 | 
								f += fmt.Sprintf(" %v", n.Left)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if n.Right != nil {
 | 
							if n.Right != nil {
 | 
				
			||||||
| 
						 | 
					@ -919,8 +919,8 @@ func stmtfmt(n *Node) string {
 | 
				
			||||||
		if simpleinit {
 | 
							if simpleinit {
 | 
				
			||||||
			f += fmt.Sprintf(" %v;", n.Ninit.N)
 | 
								f += fmt.Sprintf(" %v;", n.Ninit.N)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if n.Ntest != nil {
 | 
							if n.Left != nil {
 | 
				
			||||||
			f += Nconv(n.Ntest, 0)
 | 
								f += Nconv(n.Left, 0)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		f += fmt.Sprintf(" { %v }", n.List)
 | 
							f += fmt.Sprintf(" { %v }", n.List)
 | 
				
			||||||
| 
						 | 
					@ -1562,11 +1562,6 @@ func nodedump(n *Node, flag int) string {
 | 
				
			||||||
			fmt.Fprintf(&buf, "%v-rlist%v", Oconv(int(n.Op), 0), n.Rlist)
 | 
								fmt.Fprintf(&buf, "%v-rlist%v", Oconv(int(n.Op), 0), n.Rlist)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if n.Ntest != nil {
 | 
					 | 
				
			||||||
			indent(&buf)
 | 
					 | 
				
			||||||
			fmt.Fprintf(&buf, "%v-test%v", Oconv(int(n.Op), 0), n.Ntest)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if n.Nbody != nil {
 | 
							if n.Nbody != nil {
 | 
				
			||||||
			indent(&buf)
 | 
								indent(&buf)
 | 
				
			||||||
			fmt.Fprintf(&buf, "%v-body%v", Oconv(int(n.Op), 0), n.Nbody)
 | 
								fmt.Fprintf(&buf, "%v-body%v", Oconv(int(n.Op), 0), n.Nbody)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -790,7 +790,7 @@ func gen(n *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		gen(n.Right)                     // contin:	incr
 | 
							gen(n.Right)                     // contin:	incr
 | 
				
			||||||
		Patch(p1, Pc)                    // test:
 | 
							Patch(p1, Pc)                    // test:
 | 
				
			||||||
		Bgen(n.Ntest, false, -1, breakpc) //		if(!test) goto break
 | 
							Bgen(n.Left, false, -1, breakpc) //		if(!test) goto break
 | 
				
			||||||
		Genlist(n.Nbody)                 //		body
 | 
							Genlist(n.Nbody)                 //		body
 | 
				
			||||||
		gjmp(continpc)
 | 
							gjmp(continpc)
 | 
				
			||||||
		Patch(breakpc, Pc) // done:
 | 
							Patch(breakpc, Pc) // done:
 | 
				
			||||||
| 
						 | 
					@ -805,7 +805,7 @@ func gen(n *Node) {
 | 
				
			||||||
		p1 := gjmp(nil)                         //		goto test
 | 
							p1 := gjmp(nil)                         //		goto test
 | 
				
			||||||
		p2 := gjmp(nil)                         // p2:		goto else
 | 
							p2 := gjmp(nil)                         // p2:		goto else
 | 
				
			||||||
		Patch(p1, Pc)                           // test:
 | 
							Patch(p1, Pc)                           // test:
 | 
				
			||||||
		Bgen(n.Ntest, false, int(-n.Likely), p2) //		if(!test) goto p2
 | 
							Bgen(n.Left, false, int(-n.Likely), p2) //		if(!test) goto p2
 | 
				
			||||||
		Genlist(n.Nbody)                        //		then
 | 
							Genlist(n.Nbody)                        //		then
 | 
				
			||||||
		p3 := gjmp(nil)                         //		goto done
 | 
							p3 := gjmp(nil)                         //		goto done
 | 
				
			||||||
		Patch(p2, Pc)                           // else:
 | 
							Patch(p2, Pc)                           // else:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -700,14 +700,14 @@ for_header:
 | 
				
			||||||
		if $1 != nil {
 | 
							if $1 != nil {
 | 
				
			||||||
			$$.Ninit = list1($1);
 | 
								$$.Ninit = list1($1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		$$.Ntest = $3;
 | 
							$$.Left = $3;
 | 
				
			||||||
		$$.Right = $5;
 | 
							$$.Right = $5;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
|	osimple_stmt
 | 
					|	osimple_stmt
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// normal test
 | 
							// normal test
 | 
				
			||||||
		$$ = Nod(OFOR, nil, nil);
 | 
							$$ = Nod(OFOR, nil, nil);
 | 
				
			||||||
		$$.Ntest = $1;
 | 
							$$.Left = $1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
|	range_stmt
 | 
					|	range_stmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -734,7 +734,7 @@ if_header:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// test
 | 
							// test
 | 
				
			||||||
		$$ = Nod(OIF, nil, nil);
 | 
							$$ = Nod(OIF, nil, nil);
 | 
				
			||||||
		$$.Ntest = $1;
 | 
							$$.Left = $1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
|	osimple_stmt ';' osimple_stmt
 | 
					|	osimple_stmt ';' osimple_stmt
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -743,7 +743,7 @@ if_header:
 | 
				
			||||||
		if $1 != nil {
 | 
							if $1 != nil {
 | 
				
			||||||
			$$.Ninit = list1($1);
 | 
								$$.Ninit = list1($1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		$$.Ntest = $3;
 | 
							$$.Left = $3;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* IF cond body (ELSE IF cond body)* (ELSE block)? */
 | 
					/* IF cond body (ELSE IF cond body)* (ELSE block)? */
 | 
				
			||||||
| 
						 | 
					@ -754,7 +754,7 @@ if_stmt:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if_header
 | 
						if_header
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if $3.Ntest == nil {
 | 
							if $3.Left == nil {
 | 
				
			||||||
			Yyerror("missing condition in if statement");
 | 
								Yyerror("missing condition in if statement");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -786,7 +786,7 @@ elseif:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if_header loop_body
 | 
						if_header loop_body
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if $4.Ntest == nil {
 | 
							if $4.Left == nil {
 | 
				
			||||||
			Yyerror("missing condition in if statement");
 | 
								Yyerror("missing condition in if statement");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		$4.Nbody = $5;
 | 
							$4.Nbody = $5;
 | 
				
			||||||
| 
						 | 
					@ -821,7 +821,7 @@ switch_stmt:
 | 
				
			||||||
	if_header
 | 
						if_header
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		var n *Node
 | 
							var n *Node
 | 
				
			||||||
		n = $3.Ntest;
 | 
							n = $3.Left;
 | 
				
			||||||
		if n != nil && n.Op != OTYPESW {
 | 
							if n != nil && n.Op != OTYPESW {
 | 
				
			||||||
			n = nil;
 | 
								n = nil;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,11 +196,11 @@ func fixautoused(p *obj.Prog) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if p.From.Name == obj.NAME_AUTO && p.From.Node != nil {
 | 
							if p.From.Name == obj.NAME_AUTO && p.From.Node != nil {
 | 
				
			||||||
			p.From.Offset += ((p.From.Node).(*Node)).Stkdelta
 | 
								p.From.Offset += stkdelta[p.From.Node.(*Node)]
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if p.To.Name == obj.NAME_AUTO && p.To.Node != nil {
 | 
							if p.To.Name == obj.NAME_AUTO && p.To.Node != nil {
 | 
				
			||||||
			p.To.Offset += ((p.To.Node).(*Node)).Stkdelta
 | 
								p.To.Offset += stkdelta[p.To.Node.(*Node)]
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		lp = &p.Link
 | 
							lp = &p.Link
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,13 +123,13 @@ func fninit(n *NodeList) {
 | 
				
			||||||
	// (3)
 | 
						// (3)
 | 
				
			||||||
	a := Nod(OIF, nil, nil)
 | 
						a := Nod(OIF, nil, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	a.Ntest = Nod(ONE, gatevar, Nodintconst(0))
 | 
						a.Left = Nod(ONE, gatevar, Nodintconst(0))
 | 
				
			||||||
	r = list(r, a)
 | 
						r = list(r, a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// (4)
 | 
						// (4)
 | 
				
			||||||
	b := Nod(OIF, nil, nil)
 | 
						b := Nod(OIF, nil, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b.Ntest = Nod(OEQ, gatevar, Nodintconst(2))
 | 
						b.Left = Nod(OEQ, gatevar, Nodintconst(2))
 | 
				
			||||||
	b.Nbody = list1(Nod(ORETURN, nil, nil))
 | 
						b.Nbody = list1(Nod(ORETURN, nil, nil))
 | 
				
			||||||
	a.Nbody = list1(b)
 | 
						a.Nbody = list1(b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -231,7 +231,7 @@ func ishairy(n *Node, budget *int) bool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(*budget)--
 | 
						(*budget)--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return *budget < 0 || ishairy(n.Left, budget) || ishairy(n.Right, budget) || ishairylist(n.List, budget) || ishairylist(n.Rlist, budget) || ishairylist(n.Ninit, budget) || ishairy(n.Ntest, budget) || ishairylist(n.Nbody, budget)
 | 
						return *budget < 0 || ishairy(n.Left, budget) || ishairy(n.Right, budget) || ishairylist(n.List, budget) || ishairylist(n.Rlist, budget) || ishairylist(n.Ninit, budget) || ishairylist(n.Nbody, budget)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Inlcopy and inlcopylist recursively copy the body of a function.
 | 
					// Inlcopy and inlcopylist recursively copy the body of a function.
 | 
				
			||||||
| 
						 | 
					@ -265,7 +265,6 @@ func inlcopy(n *Node) *Node {
 | 
				
			||||||
	m.List = inlcopylist(n.List)
 | 
						m.List = inlcopylist(n.List)
 | 
				
			||||||
	m.Rlist = inlcopylist(n.Rlist)
 | 
						m.Rlist = inlcopylist(n.Rlist)
 | 
				
			||||||
	m.Ninit = inlcopylist(n.Ninit)
 | 
						m.Ninit = inlcopylist(n.Ninit)
 | 
				
			||||||
	m.Ntest = inlcopy(n.Ntest)
 | 
					 | 
				
			||||||
	m.Nbody = inlcopylist(n.Nbody)
 | 
						m.Nbody = inlcopylist(n.Nbody)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return m
 | 
						return m
 | 
				
			||||||
| 
						 | 
					@ -434,11 +433,6 @@ func inlnode(np **Node) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inlnode(&n.Ntest)
 | 
					 | 
				
			||||||
	if n.Ntest != nil && n.Ntest.Op == OINLCALL {
 | 
					 | 
				
			||||||
		inlconv2expr(&n.Ntest)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	inlnodelist(n.Nbody)
 | 
						inlnodelist(n.Nbody)
 | 
				
			||||||
	for l := n.Nbody; l != nil; l = l.Next {
 | 
						for l := n.Nbody; l != nil; l = l.Next {
 | 
				
			||||||
		if l.N.Op == OINLCALL {
 | 
							if l.N.Op == OINLCALL {
 | 
				
			||||||
| 
						 | 
					@ -965,7 +959,6 @@ func inlsubst(n *Node) *Node {
 | 
				
			||||||
	m.List = inlsubstlist(n.List)
 | 
						m.List = inlsubstlist(n.List)
 | 
				
			||||||
	m.Rlist = inlsubstlist(n.Rlist)
 | 
						m.Rlist = inlsubstlist(n.Rlist)
 | 
				
			||||||
	m.Ninit = concat(m.Ninit, inlsubstlist(n.Ninit))
 | 
						m.Ninit = concat(m.Ninit, inlsubstlist(n.Ninit))
 | 
				
			||||||
	m.Ntest = inlsubst(n.Ntest)
 | 
					 | 
				
			||||||
	m.Nbody = inlsubstlist(n.Nbody)
 | 
						m.Nbody = inlsubstlist(n.Nbody)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return m
 | 
						return m
 | 
				
			||||||
| 
						 | 
					@ -993,6 +986,5 @@ func setlno(n *Node, lno int) {
 | 
				
			||||||
	setlnolist(n.List, lno)
 | 
						setlnolist(n.List, lno)
 | 
				
			||||||
	setlnolist(n.Rlist, lno)
 | 
						setlnolist(n.Rlist, lno)
 | 
				
			||||||
	setlnolist(n.Ninit, lno)
 | 
						setlnolist(n.Ninit, lno)
 | 
				
			||||||
	setlno(n.Ntest, lno)
 | 
					 | 
				
			||||||
	setlnolist(n.Nbody, lno)
 | 
						setlnolist(n.Nbody, lno)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -646,7 +646,7 @@ func orderstmt(n *Node, order *Order) {
 | 
				
			||||||
	case OFOR:
 | 
						case OFOR:
 | 
				
			||||||
		t := marktemp(order)
 | 
							t := marktemp(order)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		orderexprinplace(&n.Ntest, order)
 | 
							orderexprinplace(&n.Left, order)
 | 
				
			||||||
		var l *NodeList
 | 
							var l *NodeList
 | 
				
			||||||
		cleantempnopop(t, order, &l)
 | 
							cleantempnopop(t, order, &l)
 | 
				
			||||||
		n.Nbody = concat(l, n.Nbody)
 | 
							n.Nbody = concat(l, n.Nbody)
 | 
				
			||||||
| 
						 | 
					@ -660,7 +660,7 @@ func orderstmt(n *Node, order *Order) {
 | 
				
			||||||
	case OIF:
 | 
						case OIF:
 | 
				
			||||||
		t := marktemp(order)
 | 
							t := marktemp(order)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		orderexprinplace(&n.Ntest, order)
 | 
							orderexprinplace(&n.Left, order)
 | 
				
			||||||
		var l *NodeList
 | 
							var l *NodeList
 | 
				
			||||||
		cleantempnopop(t, order, &l)
 | 
							cleantempnopop(t, order, &l)
 | 
				
			||||||
		n.Nbody = concat(l, n.Nbody)
 | 
							n.Nbody = concat(l, n.Nbody)
 | 
				
			||||||
| 
						 | 
					@ -793,7 +793,7 @@ func orderstmt(n *Node, order *Order) {
 | 
				
			||||||
						if t != nil && t.N.Op == ODCL && t.N.Left == r.Left {
 | 
											if t != nil && t.N.Op == ODCL && t.N.Left == r.Left {
 | 
				
			||||||
							t = t.Next
 | 
												t = t.Next
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						if t != nil && t.N.Op == ODCL && t.N.Left == r.Ntest {
 | 
											if t != nil && t.N.Op == ODCL && r.List != nil && t.N.Left == r.List.N {
 | 
				
			||||||
							t = t.Next
 | 
												t = t.Next
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						if t == nil {
 | 
											if t == nil {
 | 
				
			||||||
| 
						 | 
					@ -844,19 +844,19 @@ func orderstmt(n *Node, order *Order) {
 | 
				
			||||||
						l.N.Ninit = list(l.N.Ninit, tmp2)
 | 
											l.N.Ninit = list(l.N.Ninit, tmp2)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if r.Ntest != nil && isblank(r.Ntest) {
 | 
										if r.List != nil && isblank(r.List.N) {
 | 
				
			||||||
						r.Ntest = nil
 | 
											r.List = nil
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if r.Ntest != nil {
 | 
										if r.List != nil {
 | 
				
			||||||
						tmp1 = r.Ntest
 | 
											tmp1 = r.List.N
 | 
				
			||||||
						if r.Colas {
 | 
											if r.Colas {
 | 
				
			||||||
							tmp2 = Nod(ODCL, tmp1, nil)
 | 
												tmp2 = Nod(ODCL, tmp1, nil)
 | 
				
			||||||
							typecheck(&tmp2, Etop)
 | 
												typecheck(&tmp2, Etop)
 | 
				
			||||||
							l.N.Ninit = list(l.N.Ninit, tmp2)
 | 
												l.N.Ninit = list(l.N.Ninit, tmp2)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						r.Ntest = ordertemp(tmp1.Type, order, false)
 | 
											r.List = list1(ordertemp(tmp1.Type, order, false))
 | 
				
			||||||
						tmp2 = Nod(OAS, tmp1, r.Ntest)
 | 
											tmp2 = Nod(OAS, tmp1, r.List.N)
 | 
				
			||||||
						typecheck(&tmp2, Etop)
 | 
											typecheck(&tmp2, Etop)
 | 
				
			||||||
						l.N.Ninit = list(l.N.Ninit, tmp2)
 | 
											l.N.Ninit = list(l.N.Ninit, tmp2)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					@ -918,7 +918,7 @@ func orderstmt(n *Node, order *Order) {
 | 
				
			||||||
	case OSWITCH:
 | 
						case OSWITCH:
 | 
				
			||||||
		t := marktemp(order)
 | 
							t := marktemp(order)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		orderexpr(&n.Ntest, order, nil)
 | 
							orderexpr(&n.Left, order, nil)
 | 
				
			||||||
		for l := n.List; l != nil; l = l.Next {
 | 
							for l := n.List; l != nil; l = l.Next {
 | 
				
			||||||
			if l.N.Op != OXCASE {
 | 
								if l.N.Op != OXCASE {
 | 
				
			||||||
				Fatal("order switch case %v", Oconv(int(l.N.Op), 0))
 | 
									Fatal("order switch case %v", Oconv(int(l.N.Op), 0))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,6 +216,11 @@ func cmpstackvar(a *Node, b *Node) int {
 | 
				
			||||||
	return stringsCompare(a.Sym.Name, b.Sym.Name)
 | 
						return stringsCompare(a.Sym.Name, b.Sym.Name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// stkdelta records the stack offset delta for a node
 | 
				
			||||||
 | 
					// during the compaction of the stack frame to remove
 | 
				
			||||||
 | 
					// unused stack slots.
 | 
				
			||||||
 | 
					var stkdelta = map[*Node]int64{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
 | 
					// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
 | 
				
			||||||
func allocauto(ptxt *obj.Prog) {
 | 
					func allocauto(ptxt *obj.Prog) {
 | 
				
			||||||
	Stksize = 0
 | 
						Stksize = 0
 | 
				
			||||||
| 
						 | 
					@ -283,7 +288,7 @@ func allocauto(ptxt *obj.Prog) {
 | 
				
			||||||
			Yyerror("stack frame too large (>2GB)")
 | 
								Yyerror("stack frame too large (>2GB)")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n.Stkdelta = -Stksize - n.Xoffset
 | 
							stkdelta[n] = -Stksize - n.Xoffset
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Stksize = Rnd(Stksize, int64(Widthreg))
 | 
						Stksize = Rnd(Stksize, int64(Widthreg))
 | 
				
			||||||
| 
						 | 
					@ -296,8 +301,8 @@ func allocauto(ptxt *obj.Prog) {
 | 
				
			||||||
		if ll.N.Class != PAUTO || ll.N.Op != ONAME {
 | 
							if ll.N.Class != PAUTO || ll.N.Op != ONAME {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ll.N.Xoffset += ll.N.Stkdelta
 | 
							ll.N.Xoffset += stkdelta[ll.N]
 | 
				
			||||||
		ll.N.Stkdelta = 0
 | 
							delete(stkdelta, ll.N)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -371,18 +371,25 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 | 
				
			||||||
		Yyerror("racewalk: OGETG can happen only in runtime which we don't instrument")
 | 
							Yyerror("racewalk: OGETG can happen only in runtime which we don't instrument")
 | 
				
			||||||
		goto ret
 | 
							goto ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// just do generic traversal
 | 
					 | 
				
			||||||
	case OFOR:
 | 
						case OFOR:
 | 
				
			||||||
 | 
							if n.Left != nil {
 | 
				
			||||||
 | 
								racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if n.Right != nil {
 | 
							if n.Right != nil {
 | 
				
			||||||
			racewalknode(&n.Right, &n.Right.Ninit, 0, 0)
 | 
								racewalknode(&n.Right, &n.Right.Ninit, 0, 0)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		goto ret
 | 
							goto ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case OIF,
 | 
						case OIF, OSWITCH:
 | 
				
			||||||
		OCALLMETH,
 | 
							if n.Left != nil {
 | 
				
			||||||
 | 
								racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							goto ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// just do generic traversal
 | 
				
			||||||
 | 
						case OCALLMETH,
 | 
				
			||||||
		ORETURN,
 | 
							ORETURN,
 | 
				
			||||||
		ORETJMP,
 | 
							ORETJMP,
 | 
				
			||||||
		OSWITCH,
 | 
					 | 
				
			||||||
		OSELECT,
 | 
							OSELECT,
 | 
				
			||||||
		OEMPTY,
 | 
							OEMPTY,
 | 
				
			||||||
		OBREAK,
 | 
							OBREAK,
 | 
				
			||||||
| 
						 | 
					@ -415,9 +422,6 @@ ret:
 | 
				
			||||||
	if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
 | 
						if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
 | 
				
			||||||
		racewalklist(n.List, init)
 | 
							racewalklist(n.List, init)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if n.Ntest != nil {
 | 
					 | 
				
			||||||
		racewalknode(&n.Ntest, &n.Ntest.Ninit, 0, 0)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	racewalklist(n.Nbody, nil)
 | 
						racewalklist(n.Nbody, nil)
 | 
				
			||||||
	racewalklist(n.Rlist, nil)
 | 
						racewalklist(n.Rlist, nil)
 | 
				
			||||||
	*np = n
 | 
						*np = n
 | 
				
			||||||
| 
						 | 
					@ -577,7 +581,6 @@ func foreach(n *Node, f func(*Node, interface{}), c interface{}) {
 | 
				
			||||||
	foreachnode(n.Left, f, c)
 | 
						foreachnode(n.Left, f, c)
 | 
				
			||||||
	foreachnode(n.Right, f, c)
 | 
						foreachnode(n.Right, f, c)
 | 
				
			||||||
	foreachlist(n.List, f, c)
 | 
						foreachlist(n.List, f, c)
 | 
				
			||||||
	foreachnode(n.Ntest, f, c)
 | 
					 | 
				
			||||||
	foreachlist(n.Nbody, f, c)
 | 
						foreachlist(n.Nbody, f, c)
 | 
				
			||||||
	foreachlist(n.Rlist, f, c)
 | 
						foreachlist(n.Rlist, f, c)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,7 +201,7 @@ func walkrange(n *Node) {
 | 
				
			||||||
															n.Op = OIF
 | 
																				n.Op = OIF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
															n.Nbody = nil
 | 
																				n.Nbody = nil
 | 
				
			||||||
															n.Ntest = Nod(ONE, Nod(OLEN, a, nil), Nodintconst(0))
 | 
																				n.Left = Nod(ONE, Nod(OLEN, a, nil), Nodintconst(0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
															// hp = &a[0]
 | 
																				// hp = &a[0]
 | 
				
			||||||
															hp := temp(Ptrto(Types[TUINT8]))
 | 
																				hp := temp(Ptrto(Types[TUINT8]))
 | 
				
			||||||
| 
						 | 
					@ -231,7 +231,7 @@ func walkrange(n *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
															n.Nbody = list(n.Nbody, v1)
 | 
																				n.Nbody = list(n.Nbody, v1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
															typecheck(&n.Ntest, Erv)
 | 
																				typecheck(&n.Left, Erv)
 | 
				
			||||||
															typechecklist(n.Nbody, Etop)
 | 
																				typechecklist(n.Nbody, Etop)
 | 
				
			||||||
															walkstmt(&n)
 | 
																				walkstmt(&n)
 | 
				
			||||||
															lineno = int32(lno)
 | 
																				lineno = int32(lno)
 | 
				
			||||||
| 
						 | 
					@ -266,7 +266,7 @@ func walkrange(n *Node) {
 | 
				
			||||||
			init = list(init, Nod(OAS, hp, Nod(OADDR, tmp, nil)))
 | 
								init = list(init, Nod(OAS, hp, Nod(OADDR, tmp, nil)))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n.Ntest = Nod(OLT, hv1, hn)
 | 
							n.Left = Nod(OLT, hv1, hn)
 | 
				
			||||||
		n.Right = Nod(OAS, hv1, Nod(OADD, hv1, Nodintconst(1)))
 | 
							n.Right = Nod(OAS, hv1, Nod(OADD, hv1, Nodintconst(1)))
 | 
				
			||||||
		if v1 == nil {
 | 
							if v1 == nil {
 | 
				
			||||||
			body = nil
 | 
								body = nil
 | 
				
			||||||
| 
						 | 
					@ -313,7 +313,7 @@ func walkrange(n *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		substArgTypes(fn, t.Down, t.Type, th)
 | 
							substArgTypes(fn, t.Down, t.Type, th)
 | 
				
			||||||
		init = list(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
 | 
							init = list(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
 | 
				
			||||||
		n.Ntest = Nod(ONE, Nod(ODOT, hit, keyname), nodnil())
 | 
							n.Left = Nod(ONE, Nod(ODOT, hit, keyname), nodnil())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fn = syslook("mapiternext", 1)
 | 
							fn = syslook("mapiternext", 1)
 | 
				
			||||||
		substArgTypes(fn, th)
 | 
							substArgTypes(fn, th)
 | 
				
			||||||
| 
						 | 
					@ -338,7 +338,7 @@ func walkrange(n *Node) {
 | 
				
			||||||
	case TCHAN:
 | 
						case TCHAN:
 | 
				
			||||||
		ha := a
 | 
							ha := a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n.Ntest = nil
 | 
							n.Left = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		hv1 := temp(t.Type)
 | 
							hv1 := temp(t.Type)
 | 
				
			||||||
		hv1.Typecheck = 1
 | 
							hv1.Typecheck = 1
 | 
				
			||||||
| 
						 | 
					@ -347,12 +347,12 @@ func walkrange(n *Node) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		hb := temp(Types[TBOOL])
 | 
							hb := temp(Types[TBOOL])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n.Ntest = Nod(ONE, hb, Nodbool(false))
 | 
							n.Left = Nod(ONE, hb, Nodbool(false))
 | 
				
			||||||
		a := Nod(OAS2RECV, nil, nil)
 | 
							a := Nod(OAS2RECV, nil, nil)
 | 
				
			||||||
		a.Typecheck = 1
 | 
							a.Typecheck = 1
 | 
				
			||||||
		a.List = list(list1(hv1), hb)
 | 
							a.List = list(list1(hv1), hb)
 | 
				
			||||||
		a.Rlist = list1(Nod(ORECV, ha, nil))
 | 
							a.Rlist = list1(Nod(ORECV, ha, nil))
 | 
				
			||||||
		n.Ntest.Ninit = list1(a)
 | 
							n.Left.Ninit = list1(a)
 | 
				
			||||||
		if v1 == nil {
 | 
							if v1 == nil {
 | 
				
			||||||
			body = nil
 | 
								body = nil
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
| 
						 | 
					@ -380,8 +380,8 @@ func walkrange(n *Node) {
 | 
				
			||||||
			a.Rlist = list1(mkcall1(fn, getoutargx(fn.Type), nil, ha, hv1))
 | 
								a.Rlist = list1(mkcall1(fn, getoutargx(fn.Type), nil, ha, hv1))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n.Ntest = Nod(ONE, hv1, Nodintconst(0))
 | 
							n.Left = Nod(ONE, hv1, Nodintconst(0))
 | 
				
			||||||
		n.Ntest.Ninit = list(list1(Nod(OAS, ohv1, hv1)), a)
 | 
							n.Left.Ninit = list(list1(Nod(OAS, ohv1, hv1)), a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		body = nil
 | 
							body = nil
 | 
				
			||||||
		if v1 != nil {
 | 
							if v1 != nil {
 | 
				
			||||||
| 
						 | 
					@ -395,8 +395,8 @@ func walkrange(n *Node) {
 | 
				
			||||||
	n.Op = OFOR
 | 
						n.Op = OFOR
 | 
				
			||||||
	typechecklist(init, Etop)
 | 
						typechecklist(init, Etop)
 | 
				
			||||||
	n.Ninit = concat(n.Ninit, init)
 | 
						n.Ninit = concat(n.Ninit, init)
 | 
				
			||||||
	typechecklist(n.Ntest.Ninit, Etop)
 | 
						typechecklist(n.Left.Ninit, Etop)
 | 
				
			||||||
	typecheck(&n.Ntest, Erv)
 | 
						typecheck(&n.Left, Erv)
 | 
				
			||||||
	typecheck(&n.Right, Etop)
 | 
						typecheck(&n.Right, Etop)
 | 
				
			||||||
	typechecklist(body, Etop)
 | 
						typechecklist(body, Etop)
 | 
				
			||||||
	n.Nbody = concat(body, n.Nbody)
 | 
						n.Nbody = concat(body, n.Nbody)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,8 +65,7 @@ func typecheckselect(sel *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				n.Op = OSELRECV2
 | 
									n.Op = OSELRECV2
 | 
				
			||||||
				n.Left = n.List.N
 | 
									n.Left = n.List.N
 | 
				
			||||||
				n.Ntest = n.List.Next.N
 | 
									n.List = list1(n.List.Next.N)
 | 
				
			||||||
				n.List = nil
 | 
					 | 
				
			||||||
				n.Right = n.Rlist.N
 | 
									n.Right = n.Rlist.N
 | 
				
			||||||
				n.Rlist = nil
 | 
									n.Rlist = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,7 +130,7 @@ func walkselect(sel *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case OSELRECV, OSELRECV2:
 | 
								case OSELRECV, OSELRECV2:
 | 
				
			||||||
				ch = n.Right.Left
 | 
									ch = n.Right.Left
 | 
				
			||||||
				if n.Op == OSELRECV || n.Ntest == nil {
 | 
									if n.Op == OSELRECV || n.List == nil {
 | 
				
			||||||
					if n.Left == nil {
 | 
										if n.Left == nil {
 | 
				
			||||||
						n = n.Right
 | 
											n = n.Right
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
| 
						 | 
					@ -146,11 +145,10 @@ func walkselect(sel *Node) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				n.Op = OAS2
 | 
									n.Op = OAS2
 | 
				
			||||||
				n.List = list(list1(n.Left), n.Ntest)
 | 
									n.List = concat(list1(n.Left), n.List)
 | 
				
			||||||
				n.Rlist = list1(n.Right)
 | 
									n.Rlist = list1(n.Right)
 | 
				
			||||||
				n.Right = nil
 | 
									n.Right = nil
 | 
				
			||||||
				n.Left = nil
 | 
									n.Left = nil
 | 
				
			||||||
				n.Ntest = nil
 | 
					 | 
				
			||||||
				n.Typecheck = 0
 | 
									n.Typecheck = 0
 | 
				
			||||||
				typecheck(&n, Etop)
 | 
									typecheck(&n, Etop)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -158,7 +156,7 @@ func walkselect(sel *Node) {
 | 
				
			||||||
			// if ch == nil { block() }; n;
 | 
								// if ch == nil { block() }; n;
 | 
				
			||||||
			a := Nod(OIF, nil, nil)
 | 
								a := Nod(OIF, nil, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			a.Ntest = Nod(OEQ, ch, nodnil())
 | 
								a.Left = Nod(OEQ, ch, nodnil())
 | 
				
			||||||
			a.Nbody = list1(mkcall("block", nil, &l))
 | 
								a.Nbody = list1(mkcall("block", nil, &l))
 | 
				
			||||||
			typecheck(&a, Etop)
 | 
								typecheck(&a, Etop)
 | 
				
			||||||
			l = list(l, a)
 | 
								l = list(l, a)
 | 
				
			||||||
| 
						 | 
					@ -185,12 +183,12 @@ func walkselect(sel *Node) {
 | 
				
			||||||
			typecheck(&n.Right, Erv)
 | 
								typecheck(&n.Right, Erv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case OSELRECV, OSELRECV2:
 | 
							case OSELRECV, OSELRECV2:
 | 
				
			||||||
			if n.Op == OSELRECV2 && n.Ntest == nil {
 | 
								if n.Op == OSELRECV2 && n.List == nil {
 | 
				
			||||||
				n.Op = OSELRECV
 | 
									n.Op = OSELRECV
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if n.Op == OSELRECV2 {
 | 
								if n.Op == OSELRECV2 {
 | 
				
			||||||
				n.Ntest = Nod(OADDR, n.Ntest, nil)
 | 
									n.List.N = Nod(OADDR, n.List.N, nil)
 | 
				
			||||||
				typecheck(&n.Ntest, Erv)
 | 
									typecheck(&n.List.N, Erv)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if n.Left == nil {
 | 
								if n.Left == nil {
 | 
				
			||||||
| 
						 | 
					@ -226,7 +224,7 @@ func walkselect(sel *Node) {
 | 
				
			||||||
		case OSEND:
 | 
							case OSEND:
 | 
				
			||||||
			ch := n.Left
 | 
								ch := n.Left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			r.Ntest = mkcall1(chanfn("selectnbsend", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), ch, n.Right)
 | 
								r.Left = 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 }
 | 
								// if c != nil && selectnbrecv(&v, c) { body } else { default body }
 | 
				
			||||||
		case OSELRECV:
 | 
							case OSELRECV:
 | 
				
			||||||
| 
						 | 
					@ -234,7 +232,7 @@ func walkselect(sel *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			r.Ninit = cas.Ninit
 | 
								r.Ninit = cas.Ninit
 | 
				
			||||||
			ch := n.Right.Left
 | 
								ch := n.Right.Left
 | 
				
			||||||
			r.Ntest = mkcall1(chanfn("selectnbrecv", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, ch)
 | 
								r.Left = 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 }
 | 
								// if c != nil && selectnbrecv2(&v, c) { body } else { default body }
 | 
				
			||||||
		case OSELRECV2:
 | 
							case OSELRECV2:
 | 
				
			||||||
| 
						 | 
					@ -242,10 +240,10 @@ func walkselect(sel *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			r.Ninit = cas.Ninit
 | 
								r.Ninit = cas.Ninit
 | 
				
			||||||
			ch := n.Right.Left
 | 
								ch := n.Right.Left
 | 
				
			||||||
			r.Ntest = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, n.Ntest, ch)
 | 
								r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, n.List.N, ch)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		typecheck(&r.Ntest, Erv)
 | 
							typecheck(&r.Left, Erv)
 | 
				
			||||||
		r.Nbody = cas.Nbody
 | 
							r.Nbody = cas.Nbody
 | 
				
			||||||
		r.Rlist = concat(dflt.Ninit, dflt.Nbody)
 | 
							r.Rlist = concat(dflt.Ninit, dflt.Nbody)
 | 
				
			||||||
		sel.Nbody = list1(r)
 | 
							sel.Nbody = list1(r)
 | 
				
			||||||
| 
						 | 
					@ -282,7 +280,7 @@ func walkselect(sel *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if n == nil {
 | 
							if n == nil {
 | 
				
			||||||
			// selectdefault(sel *byte);
 | 
								// selectdefault(sel *byte);
 | 
				
			||||||
			r.Ntest = mkcall("selectdefault", Types[TBOOL], &r.Ninit, var_)
 | 
								r.Left = mkcall("selectdefault", Types[TBOOL], &r.Ninit, var_)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			switch n.Op {
 | 
								switch n.Op {
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
| 
						 | 
					@ -290,15 +288,15 @@ func walkselect(sel *Node) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
 | 
									// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
 | 
				
			||||||
			case OSEND:
 | 
								case OSEND:
 | 
				
			||||||
				r.Ntest = mkcall1(chanfn("selectsend", 2, n.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Left, n.Right)
 | 
									r.Left = 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);
 | 
									// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
 | 
				
			||||||
			case OSELRECV:
 | 
								case OSELRECV:
 | 
				
			||||||
				r.Ntest = mkcall1(chanfn("selectrecv", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left)
 | 
									r.Left = 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);
 | 
									// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
 | 
				
			||||||
			case OSELRECV2:
 | 
								case OSELRECV2:
 | 
				
			||||||
				r.Ntest = mkcall1(chanfn("selectrecv2", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left, n.Ntest)
 | 
									r.Left = mkcall1(chanfn("selectrecv2", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left, n.List.N)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -214,7 +214,6 @@ func init2(n *Node, out **NodeList) {
 | 
				
			||||||
	init1(n, out)
 | 
						init1(n, out)
 | 
				
			||||||
	init2(n.Left, out)
 | 
						init2(n.Left, out)
 | 
				
			||||||
	init2(n.Right, out)
 | 
						init2(n.Right, out)
 | 
				
			||||||
	init2(n.Ntest, out)
 | 
					 | 
				
			||||||
	init2list(n.Ninit, out)
 | 
						init2list(n.Ninit, out)
 | 
				
			||||||
	init2list(n.List, out)
 | 
						init2list(n.List, out)
 | 
				
			||||||
	init2list(n.Rlist, out)
 | 
						init2list(n.Rlist, out)
 | 
				
			||||||
| 
						 | 
					@ -996,7 +995,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 | 
				
			||||||
		a.Nbody = list1(r)
 | 
							a.Nbody = list1(r)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		a.Ninit = list1(Nod(OAS, index, Nodintconst(0)))
 | 
							a.Ninit = list1(Nod(OAS, index, Nodintconst(0)))
 | 
				
			||||||
		a.Ntest = Nod(OLT, index, Nodintconst(t.Bound))
 | 
							a.Left = Nod(OLT, index, Nodintconst(t.Bound))
 | 
				
			||||||
		a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
 | 
							a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		typecheck(&a, Etop)
 | 
							typecheck(&a, Etop)
 | 
				
			||||||
| 
						 | 
					@ -1221,6 +1220,7 @@ func oaslit(n *Node, init **NodeList) bool {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	n.Op = OEMPTY
 | 
						n.Op = OEMPTY
 | 
				
			||||||
 | 
						n.Right = nil
 | 
				
			||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2421,7 +2421,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
 | 
				
			||||||
		// generating wrapper from *T to T.
 | 
							// generating wrapper from *T to T.
 | 
				
			||||||
		n := Nod(OIF, nil, nil)
 | 
							n := Nod(OIF, nil, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n.Ntest = Nod(OEQ, this.Left, nodnil())
 | 
							n.Left = Nod(OEQ, this.Left, nodnil())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// these strings are already in the reflect tables,
 | 
							// these strings are already in the reflect tables,
 | 
				
			||||||
		// so no space cost to use them here.
 | 
							// so no space cost to use them here.
 | 
				
			||||||
| 
						 | 
					@ -2757,7 +2757,7 @@ func eqfield(p *Node, q *Node, field *Node) *Node {
 | 
				
			||||||
	nx := Nod(OXDOT, p, field)
 | 
						nx := Nod(OXDOT, p, field)
 | 
				
			||||||
	ny := Nod(OXDOT, q, field)
 | 
						ny := Nod(OXDOT, q, field)
 | 
				
			||||||
	nif := Nod(OIF, nil, nil)
 | 
						nif := Nod(OIF, nil, nil)
 | 
				
			||||||
	nif.Ntest = Nod(ONE, nx, ny)
 | 
						nif.Left = Nod(ONE, nx, ny)
 | 
				
			||||||
	r := Nod(ORETURN, nil, nil)
 | 
						r := Nod(ORETURN, nil, nil)
 | 
				
			||||||
	r.List = list(r.List, Nodbool(false))
 | 
						r.List = list(r.List, Nodbool(false))
 | 
				
			||||||
	nif.Nbody = list(nif.Nbody, r)
 | 
						nif.Nbody = list(nif.Nbody, r)
 | 
				
			||||||
| 
						 | 
					@ -2802,7 +2802,7 @@ func eqmem(p *Node, q *Node, field *Node, size int64) *Node {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nif := Nod(OIF, nil, nil)
 | 
						nif := Nod(OIF, nil, nil)
 | 
				
			||||||
	nif.Ntest = Nod(ONOT, call, nil)
 | 
						nif.Left = Nod(ONOT, call, nil)
 | 
				
			||||||
	r := Nod(ORETURN, nil, nil)
 | 
						r := Nod(ORETURN, nil, nil)
 | 
				
			||||||
	r.List = list(r.List, Nodbool(false))
 | 
						r.List = list(r.List, Nodbool(false))
 | 
				
			||||||
	nif.Nbody = list(nif.Nbody, r)
 | 
						nif.Nbody = list(nif.Nbody, r)
 | 
				
			||||||
| 
						 | 
					@ -2874,7 +2874,7 @@ func geneq(sym *Sym, t *Type) {
 | 
				
			||||||
		ny.Bounded = true
 | 
							ny.Bounded = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nif := Nod(OIF, nil, nil)
 | 
							nif := Nod(OIF, nil, nil)
 | 
				
			||||||
		nif.Ntest = Nod(ONE, nx, ny)
 | 
							nif.Left = Nod(ONE, nx, ny)
 | 
				
			||||||
		r := Nod(ORETURN, nil, nil)
 | 
							r := Nod(ORETURN, nil, nil)
 | 
				
			||||||
		r.List = list(r.List, Nodbool(false))
 | 
							r.List = list(r.List, Nodbool(false))
 | 
				
			||||||
		nif.Nbody = list(nif.Nbody, r)
 | 
							nif.Nbody = list(nif.Nbody, r)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,21 +66,21 @@ func typecheckswitch(n *Node) {
 | 
				
			||||||
	var top int
 | 
						var top int
 | 
				
			||||||
	var t *Type
 | 
						var t *Type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if n.Ntest != nil && n.Ntest.Op == OTYPESW {
 | 
						if n.Left != nil && n.Left.Op == OTYPESW {
 | 
				
			||||||
		// type switch
 | 
							// type switch
 | 
				
			||||||
		top = Etype
 | 
							top = Etype
 | 
				
			||||||
		typecheck(&n.Ntest.Right, Erv)
 | 
							typecheck(&n.Left.Right, Erv)
 | 
				
			||||||
		t = n.Ntest.Right.Type
 | 
							t = n.Left.Right.Type
 | 
				
			||||||
		if t != nil && t.Etype != TINTER {
 | 
							if t != nil && t.Etype != TINTER {
 | 
				
			||||||
			Yyerror("cannot type switch on non-interface value %v", Nconv(n.Ntest.Right, obj.FmtLong))
 | 
								Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, obj.FmtLong))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// expression switch
 | 
							// expression switch
 | 
				
			||||||
		top = Erv
 | 
							top = Erv
 | 
				
			||||||
		if n.Ntest != nil {
 | 
							if n.Left != nil {
 | 
				
			||||||
			typecheck(&n.Ntest, Erv)
 | 
								typecheck(&n.Left, Erv)
 | 
				
			||||||
			defaultlit(&n.Ntest, nil)
 | 
								defaultlit(&n.Left, nil)
 | 
				
			||||||
			t = n.Ntest.Type
 | 
								t = n.Left.Type
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			t = Types[TBOOL]
 | 
								t = Types[TBOOL]
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -88,13 +88,13 @@ func typecheckswitch(n *Node) {
 | 
				
			||||||
			var badtype *Type
 | 
								var badtype *Type
 | 
				
			||||||
			switch {
 | 
								switch {
 | 
				
			||||||
			case !okforeq[t.Etype]:
 | 
								case !okforeq[t.Etype]:
 | 
				
			||||||
				Yyerror("cannot switch on %v", Nconv(n.Ntest, obj.FmtLong))
 | 
									Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong))
 | 
				
			||||||
			case t.Etype == TARRAY && !Isfixedarray(t):
 | 
								case t.Etype == TARRAY && !Isfixedarray(t):
 | 
				
			||||||
				nilonly = "slice"
 | 
									nilonly = "slice"
 | 
				
			||||||
			case t.Etype == TARRAY && Isfixedarray(t) && algtype1(t, nil) == ANOEQ:
 | 
								case t.Etype == TARRAY && Isfixedarray(t) && algtype1(t, nil) == ANOEQ:
 | 
				
			||||||
				Yyerror("cannot switch on %v", Nconv(n.Ntest, obj.FmtLong))
 | 
									Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong))
 | 
				
			||||||
			case t.Etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ:
 | 
								case t.Etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ:
 | 
				
			||||||
				Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Ntest, obj.FmtLong), badtype)
 | 
									Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Left, obj.FmtLong), badtype)
 | 
				
			||||||
			case t.Etype == TFUNC:
 | 
								case t.Etype == TFUNC:
 | 
				
			||||||
				nilonly = "func"
 | 
									nilonly = "func"
 | 
				
			||||||
			case t.Etype == TMAP:
 | 
								case t.Etype == TMAP:
 | 
				
			||||||
| 
						 | 
					@ -133,13 +133,13 @@ func typecheckswitch(n *Node) {
 | 
				
			||||||
					case ll.N.Op == OTYPE:
 | 
										case ll.N.Op == OTYPE:
 | 
				
			||||||
						Yyerror("type %v is not an expression", ll.N.Type)
 | 
											Yyerror("type %v is not an expression", ll.N.Type)
 | 
				
			||||||
					case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0:
 | 
										case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0:
 | 
				
			||||||
						if n.Ntest != nil {
 | 
											if n.Left != nil {
 | 
				
			||||||
							Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Ntest, ll.N.Type, t)
 | 
												Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Left, ll.N.Type, t)
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
 | 
												Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					case nilonly != "" && !Isconst(ll.N, CTNIL):
 | 
										case nilonly != "" && !Isconst(ll.N, CTNIL):
 | 
				
			||||||
						Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Ntest)
 | 
											Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// type switch
 | 
									// type switch
 | 
				
			||||||
| 
						 | 
					@ -151,12 +151,12 @@ func typecheckswitch(n *Node) {
 | 
				
			||||||
					case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||?
 | 
										case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||?
 | 
				
			||||||
						Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong))
 | 
											Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong))
 | 
				
			||||||
						// reset to original type
 | 
											// reset to original type
 | 
				
			||||||
						ll.N = n.Ntest.Right
 | 
											ll.N = n.Left.Right
 | 
				
			||||||
					case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
 | 
										case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
 | 
				
			||||||
						if have != nil && missing.Broke == 0 && have.Broke == 0 {
 | 
											if have != nil && missing.Broke == 0 && have.Broke == 0 {
 | 
				
			||||||
							Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Ntest.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
 | 
												Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
 | 
				
			||||||
						} else if missing.Broke == 0 {
 | 
											} else if missing.Broke == 0 {
 | 
				
			||||||
							Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Ntest.Right, obj.FmtLong), ll.N.Type, missing.Sym)
 | 
												Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -189,22 +189,18 @@ func typecheckswitch(n *Node) {
 | 
				
			||||||
// walkswitch walks a switch statement.
 | 
					// walkswitch walks a switch statement.
 | 
				
			||||||
func walkswitch(sw *Node) {
 | 
					func walkswitch(sw *Node) {
 | 
				
			||||||
	// convert switch {...} to switch true {...}
 | 
						// convert switch {...} to switch true {...}
 | 
				
			||||||
	if sw.Ntest == nil {
 | 
						if sw.Left == nil {
 | 
				
			||||||
		sw.Ntest = Nodbool(true)
 | 
							sw.Left = Nodbool(true)
 | 
				
			||||||
		typecheck(&sw.Ntest, Erv)
 | 
							typecheck(&sw.Left, Erv)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if sw.Ntest.Op == OTYPESW {
 | 
						if sw.Left.Op == OTYPESW {
 | 
				
			||||||
		var s typeSwitch
 | 
							var s typeSwitch
 | 
				
			||||||
		s.walk(sw)
 | 
							s.walk(sw)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		var s exprSwitch
 | 
							var s exprSwitch
 | 
				
			||||||
		s.walk(sw)
 | 
							s.walk(sw)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Discard old AST elements. They can confuse racewalk.
 | 
					 | 
				
			||||||
	sw.Ntest = nil
 | 
					 | 
				
			||||||
	sw.List = nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// walk generates an AST implementing sw.
 | 
					// walk generates an AST implementing sw.
 | 
				
			||||||
| 
						 | 
					@ -215,15 +211,18 @@ func walkswitch(sw *Node) {
 | 
				
			||||||
func (s *exprSwitch) walk(sw *Node) {
 | 
					func (s *exprSwitch) walk(sw *Node) {
 | 
				
			||||||
	casebody(sw, nil)
 | 
						casebody(sw, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cond := sw.Left
 | 
				
			||||||
 | 
						sw.Left = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s.kind = switchKindExpr
 | 
						s.kind = switchKindExpr
 | 
				
			||||||
	if Isconst(sw.Ntest, CTBOOL) {
 | 
						if Isconst(cond, CTBOOL) {
 | 
				
			||||||
		s.kind = switchKindTrue
 | 
							s.kind = switchKindTrue
 | 
				
			||||||
		if !sw.Ntest.Val.U.(bool) {
 | 
							if !cond.Val.U.(bool) {
 | 
				
			||||||
			s.kind = switchKindFalse
 | 
								s.kind = switchKindFalse
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	walkexpr(&sw.Ntest, &sw.Ninit)
 | 
						walkexpr(&cond, &sw.Ninit)
 | 
				
			||||||
	t := sw.Type
 | 
						t := sw.Type
 | 
				
			||||||
	if t == nil {
 | 
						if t == nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
| 
						 | 
					@ -233,17 +232,18 @@ func (s *exprSwitch) walk(sw *Node) {
 | 
				
			||||||
	var cas *NodeList
 | 
						var cas *NodeList
 | 
				
			||||||
	if s.kind == switchKindTrue || s.kind == switchKindFalse {
 | 
						if s.kind == switchKindTrue || s.kind == switchKindFalse {
 | 
				
			||||||
		s.exprname = Nodbool(s.kind == switchKindTrue)
 | 
							s.exprname = Nodbool(s.kind == switchKindTrue)
 | 
				
			||||||
	} else if consttype(sw.Ntest) >= 0 {
 | 
						} else if consttype(cond) >= 0 {
 | 
				
			||||||
		// leave constants to enable dead code elimination (issue 9608)
 | 
							// leave constants to enable dead code elimination (issue 9608)
 | 
				
			||||||
		s.exprname = sw.Ntest
 | 
							s.exprname = cond
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		s.exprname = temp(sw.Ntest.Type)
 | 
							s.exprname = temp(cond.Type)
 | 
				
			||||||
		cas = list1(Nod(OAS, s.exprname, sw.Ntest))
 | 
							cas = list1(Nod(OAS, s.exprname, cond))
 | 
				
			||||||
		typechecklist(cas, Etop)
 | 
							typechecklist(cas, Etop)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// enumerate the cases, and lop off the default case
 | 
						// enumerate the cases, and lop off the default case
 | 
				
			||||||
	cc := caseClauses(sw, s.kind)
 | 
						cc := caseClauses(sw, s.kind)
 | 
				
			||||||
 | 
						sw.List = nil
 | 
				
			||||||
	var def *Node
 | 
						var def *Node
 | 
				
			||||||
	if len(cc) > 0 && cc[0].typ == caseKindDefault {
 | 
						if len(cc) > 0 && cc[0].typ == caseKindDefault {
 | 
				
			||||||
		def = cc[0].node.Right
 | 
							def = cc[0].node.Right
 | 
				
			||||||
| 
						 | 
					@ -278,9 +278,9 @@ func (s *exprSwitch) walk(sw *Node) {
 | 
				
			||||||
	if nerrors == 0 {
 | 
						if nerrors == 0 {
 | 
				
			||||||
		cas = list(cas, def)
 | 
							cas = list(cas, def)
 | 
				
			||||||
		sw.Nbody = concat(cas, sw.Nbody)
 | 
							sw.Nbody = concat(cas, sw.Nbody)
 | 
				
			||||||
		sw.List = nil
 | 
					 | 
				
			||||||
		walkstmtlist(sw.Nbody)
 | 
							walkstmtlist(sw.Nbody)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// walkCases generates an AST implementing the cases in cc.
 | 
					// walkCases generates an AST implementing the cases in cc.
 | 
				
			||||||
| 
						 | 
					@ -294,14 +294,14 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			a := Nod(OIF, nil, nil)
 | 
								a := Nod(OIF, nil, nil)
 | 
				
			||||||
			if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE {
 | 
								if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE {
 | 
				
			||||||
				a.Ntest = Nod(OEQ, s.exprname, n.Left) // if name == val
 | 
									a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val
 | 
				
			||||||
				typecheck(&a.Ntest, Erv)
 | 
									typecheck(&a.Left, Erv)
 | 
				
			||||||
			} else if s.kind == switchKindTrue {
 | 
								} else if s.kind == switchKindTrue {
 | 
				
			||||||
				a.Ntest = n.Left // if val
 | 
									a.Left = n.Left // if val
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				// s.kind == switchKindFalse
 | 
									// s.kind == switchKindFalse
 | 
				
			||||||
				a.Ntest = Nod(ONOT, n.Left, nil) // if !val
 | 
									a.Left = Nod(ONOT, n.Left, nil) // if !val
 | 
				
			||||||
				typecheck(&a.Ntest, Erv)
 | 
									typecheck(&a.Left, Erv)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			a.Nbody = list1(n.Right) // goto l
 | 
								a.Nbody = list1(n.Right) // goto l
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,11 +320,11 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
 | 
				
			||||||
		// Search by length and then by value; see exprcmp.
 | 
							// Search by length and then by value; see exprcmp.
 | 
				
			||||||
		lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
 | 
							lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
 | 
				
			||||||
		leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
 | 
							leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
 | 
				
			||||||
		a.Ntest = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le))
 | 
							a.Left = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le))
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		a.Ntest = le
 | 
							a.Left = le
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	typecheck(&a.Ntest, Erv)
 | 
						typecheck(&a.Left, Erv)
 | 
				
			||||||
	a.Nbody = list1(s.walkCases(cc[:half]))
 | 
						a.Nbody = list1(s.walkCases(cc[:half]))
 | 
				
			||||||
	a.Rlist = list1(s.walkCases(cc[half:]))
 | 
						a.Rlist = list1(s.walkCases(cc[half:]))
 | 
				
			||||||
	return a
 | 
						return a
 | 
				
			||||||
| 
						 | 
					@ -512,17 +512,21 @@ func caseClauses(sw *Node, kind int) []*caseClause {
 | 
				
			||||||
// search using if..goto, although binary search
 | 
					// search using if..goto, although binary search
 | 
				
			||||||
// is used with long runs of concrete types.
 | 
					// is used with long runs of concrete types.
 | 
				
			||||||
func (s *typeSwitch) walk(sw *Node) {
 | 
					func (s *typeSwitch) walk(sw *Node) {
 | 
				
			||||||
	if sw.Ntest == nil {
 | 
						cond := sw.Left
 | 
				
			||||||
 | 
						sw.Left = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cond == nil {
 | 
				
			||||||
 | 
							sw.List = nil
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if sw.Ntest.Right == nil {
 | 
						if cond.Right == nil {
 | 
				
			||||||
		setlineno(sw)
 | 
							setlineno(sw)
 | 
				
			||||||
		Yyerror("type switch must have an assignment")
 | 
							Yyerror("type switch must have an assignment")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	walkexpr(&sw.Ntest.Right, &sw.Ninit)
 | 
						walkexpr(&cond.Right, &sw.Ninit)
 | 
				
			||||||
	if !Istype(sw.Ntest.Right.Type, TINTER) {
 | 
						if !Istype(cond.Right.Type, TINTER) {
 | 
				
			||||||
		Yyerror("type switch must be on an interface")
 | 
							Yyerror("type switch must be on an interface")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -530,9 +534,9 @@ func (s *typeSwitch) walk(sw *Node) {
 | 
				
			||||||
	var cas *NodeList
 | 
						var cas *NodeList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// predeclare temporary variables and the boolean var
 | 
						// predeclare temporary variables and the boolean var
 | 
				
			||||||
	s.facename = temp(sw.Ntest.Right.Type)
 | 
						s.facename = temp(cond.Right.Type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	a := Nod(OAS, s.facename, sw.Ntest.Right)
 | 
						a := Nod(OAS, s.facename, cond.Right)
 | 
				
			||||||
	typecheck(&a, Etop)
 | 
						typecheck(&a, Etop)
 | 
				
			||||||
	cas = list(cas, a)
 | 
						cas = list(cas, a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -546,7 +550,7 @@ func (s *typeSwitch) walk(sw *Node) {
 | 
				
			||||||
	casebody(sw, s.facename)
 | 
						casebody(sw, s.facename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// calculate type hash
 | 
						// calculate type hash
 | 
				
			||||||
	t := sw.Ntest.Right.Type
 | 
						t := cond.Right.Type
 | 
				
			||||||
	if isnilinter(t) {
 | 
						if isnilinter(t) {
 | 
				
			||||||
		a = syslook("efacethash", 1)
 | 
							a = syslook("efacethash", 1)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -560,6 +564,7 @@ func (s *typeSwitch) walk(sw *Node) {
 | 
				
			||||||
	cas = list(cas, a)
 | 
						cas = list(cas, a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cc := caseClauses(sw, switchKindType)
 | 
						cc := caseClauses(sw, switchKindType)
 | 
				
			||||||
 | 
						sw.List = nil
 | 
				
			||||||
	var def *Node
 | 
						var def *Node
 | 
				
			||||||
	if len(cc) > 0 && cc[0].typ == caseKindDefault {
 | 
						if len(cc) > 0 && cc[0].typ == caseKindDefault {
 | 
				
			||||||
		def = cc[0].node.Right
 | 
							def = cc[0].node.Right
 | 
				
			||||||
| 
						 | 
					@ -576,8 +581,8 @@ func (s *typeSwitch) walk(sw *Node) {
 | 
				
			||||||
			var v Val
 | 
								var v Val
 | 
				
			||||||
			v.Ctype = CTNIL
 | 
								v.Ctype = CTNIL
 | 
				
			||||||
			a = Nod(OIF, nil, nil)
 | 
								a = Nod(OIF, nil, nil)
 | 
				
			||||||
			a.Ntest = Nod(OEQ, s.facename, nodlit(v))
 | 
								a.Left = Nod(OEQ, s.facename, nodlit(v))
 | 
				
			||||||
			typecheck(&a.Ntest, Erv)
 | 
								typecheck(&a.Left, Erv)
 | 
				
			||||||
			a.Nbody = list1(n.Right) // if i==nil { goto l }
 | 
								a.Nbody = list1(n.Right) // if i==nil { goto l }
 | 
				
			||||||
			n.Right = a
 | 
								n.Right = a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -658,7 +663,7 @@ func (s *typeSwitch) typeone(t *Node) *Node {
 | 
				
			||||||
	init = list(init, a)
 | 
						init = list(init, a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c := Nod(OIF, nil, nil)
 | 
						c := Nod(OIF, nil, nil)
 | 
				
			||||||
	c.Ntest = s.okname
 | 
						c.Left = s.okname
 | 
				
			||||||
	c.Nbody = list1(t.Right) // if ok { goto l }
 | 
						c.Nbody = list1(t.Right) // if ok { goto l }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return liststmt(list(init, c))
 | 
						return liststmt(list(init, c))
 | 
				
			||||||
| 
						 | 
					@ -674,8 +679,8 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
 | 
				
			||||||
				Fatal("typeSwitch walkCases")
 | 
									Fatal("typeSwitch walkCases")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			a := Nod(OIF, nil, nil)
 | 
								a := Nod(OIF, nil, nil)
 | 
				
			||||||
			a.Ntest = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
 | 
								a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
 | 
				
			||||||
			typecheck(&a.Ntest, Erv)
 | 
								typecheck(&a.Left, Erv)
 | 
				
			||||||
			a.Nbody = list1(n.Right)
 | 
								a.Nbody = list1(n.Right)
 | 
				
			||||||
			cas = list(cas, a)
 | 
								cas = list(cas, a)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -685,8 +690,8 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
 | 
				
			||||||
	// find the middle and recur
 | 
						// find the middle and recur
 | 
				
			||||||
	half := len(cc) / 2
 | 
						half := len(cc) / 2
 | 
				
			||||||
	a := Nod(OIF, nil, nil)
 | 
						a := Nod(OIF, nil, nil)
 | 
				
			||||||
	a.Ntest = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
 | 
						a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
 | 
				
			||||||
	typecheck(&a.Ntest, Erv)
 | 
						typecheck(&a.Left, Erv)
 | 
				
			||||||
	a.Nbody = list1(s.walkCases(cc[:half]))
 | 
						a.Nbody = list1(s.walkCases(cc[:half]))
 | 
				
			||||||
	a.Rlist = list1(s.walkCases(cc[half:]))
 | 
						a.Rlist = list1(s.walkCases(cc[half:]))
 | 
				
			||||||
	return a
 | 
						return a
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,6 @@ type Node struct {
 | 
				
			||||||
	// Generic recursive walks should follow these fields.
 | 
						// Generic recursive walks should follow these fields.
 | 
				
			||||||
	Left  *Node
 | 
						Left  *Node
 | 
				
			||||||
	Right *Node
 | 
						Right *Node
 | 
				
			||||||
	Ntest *Node
 | 
					 | 
				
			||||||
	Ninit *NodeList
 | 
						Ninit *NodeList
 | 
				
			||||||
	Nbody *NodeList
 | 
						Nbody *NodeList
 | 
				
			||||||
	List  *NodeList
 | 
						List  *NodeList
 | 
				
			||||||
| 
						 | 
					@ -55,7 +54,6 @@ type Node struct {
 | 
				
			||||||
	Val Val
 | 
						Val Val
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Xoffset int64
 | 
						Xoffset int64
 | 
				
			||||||
	Stkdelta int64 // offset added by stack frame compaction phase.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Escape analysis.
 | 
						// Escape analysis.
 | 
				
			||||||
	Escloopdepth int32 // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
 | 
						Escloopdepth int32 // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -237,7 +237,7 @@ func callrecv(n *Node) bool {
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return callrecv(n.Left) || callrecv(n.Right) || callrecv(n.Ntest) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
 | 
						return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func callrecvlist(l *NodeList) bool {
 | 
					func callrecvlist(l *NodeList) bool {
 | 
				
			||||||
| 
						 | 
					@ -2097,11 +2097,11 @@ OpSwitch:
 | 
				
			||||||
		ok |= Etop
 | 
							ok |= Etop
 | 
				
			||||||
		typechecklist(n.Ninit, Etop)
 | 
							typechecklist(n.Ninit, Etop)
 | 
				
			||||||
		decldepth++
 | 
							decldepth++
 | 
				
			||||||
		typecheck(&n.Ntest, Erv)
 | 
							typecheck(&n.Left, Erv)
 | 
				
			||||||
		if n.Ntest != nil {
 | 
							if n.Left != nil {
 | 
				
			||||||
			t := n.Ntest.Type
 | 
								t := n.Left.Type
 | 
				
			||||||
			if t != nil && t.Etype != TBOOL {
 | 
								if t != nil && t.Etype != TBOOL {
 | 
				
			||||||
				Yyerror("non-bool %v used as for condition", Nconv(n.Ntest, obj.FmtLong))
 | 
									Yyerror("non-bool %v used as for condition", Nconv(n.Left, obj.FmtLong))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		typecheck(&n.Right, Etop)
 | 
							typecheck(&n.Right, Etop)
 | 
				
			||||||
| 
						 | 
					@ -2112,11 +2112,11 @@ OpSwitch:
 | 
				
			||||||
	case OIF:
 | 
						case OIF:
 | 
				
			||||||
		ok |= Etop
 | 
							ok |= Etop
 | 
				
			||||||
		typechecklist(n.Ninit, Etop)
 | 
							typechecklist(n.Ninit, Etop)
 | 
				
			||||||
		typecheck(&n.Ntest, Erv)
 | 
							typecheck(&n.Left, Erv)
 | 
				
			||||||
		if n.Ntest != nil {
 | 
							if n.Left != nil {
 | 
				
			||||||
			t := n.Ntest.Type
 | 
								t := n.Left.Type
 | 
				
			||||||
			if t != nil && t.Etype != TBOOL {
 | 
								if t != nil && t.Etype != TBOOL {
 | 
				
			||||||
				Yyerror("non-bool %v used as if condition", Nconv(n.Ntest, obj.FmtLong))
 | 
									Yyerror("non-bool %v used as if condition", Nconv(n.Left, obj.FmtLong))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		typechecklist(n.Nbody, Etop)
 | 
							typechecklist(n.Nbody, Etop)
 | 
				
			||||||
| 
						 | 
					@ -2811,7 +2811,7 @@ func fielddup(n *Node, hash map[string]bool) {
 | 
				
			||||||
	hash[name] = true
 | 
						hash[name] = true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func keydup(n *Node, hash []*Node) {
 | 
					func keydup(n *Node, hash map[uint32][]*Node) {
 | 
				
			||||||
	orign := n
 | 
						orign := n
 | 
				
			||||||
	if n.Op == OCONVIFACE {
 | 
						if n.Op == OCONVIFACE {
 | 
				
			||||||
		n = n.Left
 | 
							n = n.Left
 | 
				
			||||||
| 
						 | 
					@ -2846,9 +2846,8 @@ func keydup(n *Node, hash []*Node) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h := uint(b % uint32(len(hash)))
 | 
					 | 
				
			||||||
	var cmp Node
 | 
						var cmp Node
 | 
				
			||||||
	for a := hash[h]; a != nil; a = a.Ntest {
 | 
						for _, a := range hash[b] {
 | 
				
			||||||
		cmp.Op = OEQ
 | 
							cmp.Op = OEQ
 | 
				
			||||||
		cmp.Left = n
 | 
							cmp.Left = n
 | 
				
			||||||
		b = 0
 | 
							b = 0
 | 
				
			||||||
| 
						 | 
					@ -2870,75 +2869,20 @@ func keydup(n *Node, hash []*Node) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	orign.Ntest = hash[h]
 | 
						hash[b] = append(hash[b], orign)
 | 
				
			||||||
	hash[h] = orign
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func indexdup(n *Node, hash []*Node) {
 | 
					func indexdup(n *Node, hash map[int64]*Node) {
 | 
				
			||||||
	if n.Op != OLITERAL {
 | 
						if n.Op != OLITERAL {
 | 
				
			||||||
		Fatal("indexdup: not OLITERAL")
 | 
							Fatal("indexdup: not OLITERAL")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b := uint32(Mpgetfix(n.Val.U.(*Mpint)))
 | 
						v := Mpgetfix(n.Val.U.(*Mpint))
 | 
				
			||||||
	h := uint(b % uint32(len(hash)))
 | 
						if hash[v] != nil {
 | 
				
			||||||
	var c uint32
 | 
							Yyerror("duplicate index in array literal: %d", v)
 | 
				
			||||||
	for a := hash[h]; a != nil; a = a.Ntest {
 | 
					 | 
				
			||||||
		c = uint32(Mpgetfix(a.Val.U.(*Mpint)))
 | 
					 | 
				
			||||||
		if b == c {
 | 
					 | 
				
			||||||
			Yyerror("duplicate index in array literal: %d", b)
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
						hash[v] = n
 | 
				
			||||||
 | 
					 | 
				
			||||||
	n.Ntest = hash[h]
 | 
					 | 
				
			||||||
	hash[h] = n
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func prime(h uint32, sr uint32) bool {
 | 
					 | 
				
			||||||
	for n := uint32(3); n <= sr; n += 2 {
 | 
					 | 
				
			||||||
		if h%n == 0 {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func inithash(n *Node, autohash []*Node) []*Node {
 | 
					 | 
				
			||||||
	// count the number of entries
 | 
					 | 
				
			||||||
	h := uint32(0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for ll := n.List; ll != nil; ll = ll.Next {
 | 
					 | 
				
			||||||
		h++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if the auto hash table is
 | 
					 | 
				
			||||||
	// large enough use it.
 | 
					 | 
				
			||||||
	if h <= uint32(len(autohash)) {
 | 
					 | 
				
			||||||
		for i := range autohash {
 | 
					 | 
				
			||||||
			autohash[i] = nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return autohash
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// make hash size odd and 12% larger than entries
 | 
					 | 
				
			||||||
	h += h / 8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	h |= 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// calculate sqrt of h
 | 
					 | 
				
			||||||
	sr := h / 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < 5; i++ {
 | 
					 | 
				
			||||||
		sr = (sr + h/sr) / 2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// check for primeality
 | 
					 | 
				
			||||||
	for !prime(h, sr) {
 | 
					 | 
				
			||||||
		h += 2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// build and return a throw-away hash table
 | 
					 | 
				
			||||||
	return make([]*Node, h)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func iscomptype(t *Type) bool {
 | 
					func iscomptype(t *Type) bool {
 | 
				
			||||||
| 
						 | 
					@ -3031,9 +2975,14 @@ func typecheckcomplit(np **Node) {
 | 
				
			||||||
		n.Type = nil
 | 
							n.Type = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case TARRAY:
 | 
						case TARRAY:
 | 
				
			||||||
		var autohash [101]*Node
 | 
							// Only allocate hash if there are some key/value pairs.
 | 
				
			||||||
		hash := inithash(n, autohash[:])
 | 
							var hash map[int64]*Node
 | 
				
			||||||
 | 
							for ll := n.List; ll != nil; ll = ll.Next {
 | 
				
			||||||
 | 
								if ll.N.Op == OKEY {
 | 
				
			||||||
 | 
									hash = make(map[int64]*Node)
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		length := int64(0)
 | 
							length := int64(0)
 | 
				
			||||||
		i := 0
 | 
							i := 0
 | 
				
			||||||
		var l *Node
 | 
							var l *Node
 | 
				
			||||||
| 
						 | 
					@ -3056,7 +3005,7 @@ func typecheckcomplit(np **Node) {
 | 
				
			||||||
				i = -(1 << 30) // stay negative for a while
 | 
									i = -(1 << 30) // stay negative for a while
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if i >= 0 {
 | 
								if i >= 0 && hash != nil {
 | 
				
			||||||
				indexdup(l.Left, hash)
 | 
									indexdup(l.Left, hash)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			i++
 | 
								i++
 | 
				
			||||||
| 
						 | 
					@ -3085,9 +3034,7 @@ func typecheckcomplit(np **Node) {
 | 
				
			||||||
		n.Op = OARRAYLIT
 | 
							n.Op = OARRAYLIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case TMAP:
 | 
						case TMAP:
 | 
				
			||||||
		var autohash [101]*Node
 | 
							hash := make(map[uint32][]*Node)
 | 
				
			||||||
		hash := inithash(n, autohash[:])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		var l *Node
 | 
							var l *Node
 | 
				
			||||||
		for ll := n.List; ll != nil; ll = ll.Next {
 | 
							for ll := n.List; ll != nil; ll = ll.Next {
 | 
				
			||||||
			l = ll.N
 | 
								l = ll.N
 | 
				
			||||||
| 
						 | 
					@ -3952,7 +3899,6 @@ func markbreak(n *Node, implicit *Node) {
 | 
				
			||||||
		markbreak(n.Left, implicit)
 | 
							markbreak(n.Left, implicit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		markbreak(n.Right, implicit)
 | 
							markbreak(n.Right, implicit)
 | 
				
			||||||
		markbreak(n.Ntest, implicit)
 | 
					 | 
				
			||||||
		markbreaklist(n.Ninit, implicit)
 | 
							markbreaklist(n.Ninit, implicit)
 | 
				
			||||||
		markbreaklist(n.Nbody, implicit)
 | 
							markbreaklist(n.Nbody, implicit)
 | 
				
			||||||
		markbreaklist(n.List, implicit)
 | 
							markbreaklist(n.List, implicit)
 | 
				
			||||||
| 
						 | 
					@ -4024,7 +3970,7 @@ func isterminating(l *NodeList, top int) bool {
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case OFOR:
 | 
						case OFOR:
 | 
				
			||||||
		if n.Ntest != nil {
 | 
							if n.Left != nil {
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if n.Hasbreak {
 | 
							if n.Hasbreak {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,19 +247,19 @@ func walkstmt(np **Node) {
 | 
				
			||||||
		adjustargs(n, 2*Widthptr)
 | 
							adjustargs(n, 2*Widthptr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case OFOR:
 | 
						case OFOR:
 | 
				
			||||||
		if n.Ntest != nil {
 | 
							if n.Left != nil {
 | 
				
			||||||
			walkstmtlist(n.Ntest.Ninit)
 | 
								walkstmtlist(n.Left.Ninit)
 | 
				
			||||||
			init := n.Ntest.Ninit
 | 
								init := n.Left.Ninit
 | 
				
			||||||
			n.Ntest.Ninit = nil
 | 
								n.Left.Ninit = nil
 | 
				
			||||||
			walkexpr(&n.Ntest, &init)
 | 
								walkexpr(&n.Left, &init)
 | 
				
			||||||
			addinit(&n.Ntest, init)
 | 
								addinit(&n.Left, init)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		walkstmt(&n.Right)
 | 
							walkstmt(&n.Right)
 | 
				
			||||||
		walkstmtlist(n.Nbody)
 | 
							walkstmtlist(n.Nbody)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case OIF:
 | 
						case OIF:
 | 
				
			||||||
		walkexpr(&n.Ntest, &n.Ninit)
 | 
							walkexpr(&n.Left, &n.Ninit)
 | 
				
			||||||
		walkstmtlist(n.Nbody)
 | 
							walkstmtlist(n.Nbody)
 | 
				
			||||||
		walkstmtlist(n.Rlist)
 | 
							walkstmtlist(n.Rlist)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1043,7 +1043,7 @@ func walkexpr(np **Node, init **NodeList) {
 | 
				
			||||||
				walkexpr(&n1, init)
 | 
									walkexpr(&n1, init)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				n2 := Nod(OIF, nil, nil)
 | 
									n2 := Nod(OIF, nil, nil)
 | 
				
			||||||
				n2.Ntest = Nod(OEQ, l, nodnil())
 | 
									n2.Left = Nod(OEQ, l, nodnil())
 | 
				
			||||||
				n2.Nbody = list1(Nod(OAS, l, n1))
 | 
									n2.Nbody = list1(Nod(OAS, l, n1))
 | 
				
			||||||
				n2.Likely = -1
 | 
									n2.Likely = -1
 | 
				
			||||||
				typecheck(&n2, Etop)
 | 
									typecheck(&n2, Etop)
 | 
				
			||||||
| 
						 | 
					@ -2914,7 +2914,7 @@ func appendslice(n *Node, init **NodeList) *Node {
 | 
				
			||||||
	// n := len(s) + len(l2) - cap(s)
 | 
						// n := len(s) + len(l2) - cap(s)
 | 
				
			||||||
	nif.Ninit = list1(Nod(OAS, nt, Nod(OSUB, Nod(OADD, Nod(OLEN, s, nil), Nod(OLEN, l2, nil)), Nod(OCAP, s, nil))))
 | 
						nif.Ninit = list1(Nod(OAS, nt, Nod(OSUB, Nod(OADD, Nod(OLEN, s, nil), Nod(OLEN, l2, nil)), Nod(OCAP, s, nil))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nif.Ntest = Nod(OGT, nt, Nodintconst(0))
 | 
						nif.Left = Nod(OGT, nt, Nodintconst(0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// instantiate growslice(Type*, []any, int) []any
 | 
						// instantiate growslice(Type*, []any, int) []any
 | 
				
			||||||
	fn := syslook("growslice", 1) //   growslice(<type>, old []T, n int64) (ret []T)
 | 
						fn := syslook("growslice", 1) //   growslice(<type>, old []T, n int64) (ret []T)
 | 
				
			||||||
| 
						 | 
					@ -3046,7 +3046,7 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	na := Nodintconst(int64(argc)) // const argc
 | 
						na := Nodintconst(int64(argc)) // const argc
 | 
				
			||||||
	nx := Nod(OIF, nil, nil)       // if cap(s) - len(s) < argc
 | 
						nx := Nod(OIF, nil, nil)       // if cap(s) - len(s) < argc
 | 
				
			||||||
	nx.Ntest = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
 | 
						nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn := syslook("growslice", 1) //   growslice(<type>, old []T, n int) (ret []T)
 | 
						fn := syslook("growslice", 1) //   growslice(<type>, old []T, n int) (ret []T)
 | 
				
			||||||
	substArgTypes(fn, ns.Type.Type, ns.Type.Type)
 | 
						substArgTypes(fn, ns.Type.Type, ns.Type.Type)
 | 
				
			||||||
| 
						 | 
					@ -3124,7 +3124,7 @@ func copyany(n *Node, init **NodeList, runtimecall int) *Node {
 | 
				
			||||||
	// if n > len(frm) { n = len(frm) }
 | 
						// if n > len(frm) { n = len(frm) }
 | 
				
			||||||
	nif := Nod(OIF, nil, nil)
 | 
						nif := Nod(OIF, nil, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nif.Ntest = Nod(OGT, nlen, Nod(OLEN, nr, nil))
 | 
						nif.Left = Nod(OGT, nlen, Nod(OLEN, nr, nil))
 | 
				
			||||||
	nif.Nbody = list(nif.Nbody, Nod(OAS, nlen, Nod(OLEN, nr, nil)))
 | 
						nif.Nbody = list(nif.Nbody, Nod(OAS, nlen, Nod(OLEN, nr, nil)))
 | 
				
			||||||
	l = list(l, nif)
 | 
						l = list(l, nif)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3982,7 +3982,7 @@ func candiscard(n *Node) bool {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !candiscard(n.Left) || !candiscard(n.Right) || !candiscard(n.Ntest) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
 | 
						if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1788,7 +1788,7 @@ yydefault:
 | 
				
			||||||
			if yyDollar[1].node != nil {
 | 
								if yyDollar[1].node != nil {
 | 
				
			||||||
				yyVAL.node.Ninit = list1(yyDollar[1].node)
 | 
									yyVAL.node.Ninit = list1(yyDollar[1].node)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			yyVAL.node.Ntest = yyDollar[3].node
 | 
								yyVAL.node.Left = yyDollar[3].node
 | 
				
			||||||
			yyVAL.node.Right = yyDollar[5].node
 | 
								yyVAL.node.Right = yyDollar[5].node
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case 71:
 | 
						case 71:
 | 
				
			||||||
| 
						 | 
					@ -1797,7 +1797,7 @@ yydefault:
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			// normal test
 | 
								// normal test
 | 
				
			||||||
			yyVAL.node = Nod(OFOR, nil, nil)
 | 
								yyVAL.node = Nod(OFOR, nil, nil)
 | 
				
			||||||
			yyVAL.node.Ntest = yyDollar[1].node
 | 
								yyVAL.node.Left = yyDollar[1].node
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case 73:
 | 
						case 73:
 | 
				
			||||||
		yyDollar = yyS[yypt-2 : yypt+1]
 | 
							yyDollar = yyS[yypt-2 : yypt+1]
 | 
				
			||||||
| 
						 | 
					@ -1825,7 +1825,7 @@ yydefault:
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			// test
 | 
								// test
 | 
				
			||||||
			yyVAL.node = Nod(OIF, nil, nil)
 | 
								yyVAL.node = Nod(OIF, nil, nil)
 | 
				
			||||||
			yyVAL.node.Ntest = yyDollar[1].node
 | 
								yyVAL.node.Left = yyDollar[1].node
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case 77:
 | 
						case 77:
 | 
				
			||||||
		yyDollar = yyS[yypt-3 : yypt+1]
 | 
							yyDollar = yyS[yypt-3 : yypt+1]
 | 
				
			||||||
| 
						 | 
					@ -1836,7 +1836,7 @@ yydefault:
 | 
				
			||||||
			if yyDollar[1].node != nil {
 | 
								if yyDollar[1].node != nil {
 | 
				
			||||||
				yyVAL.node.Ninit = list1(yyDollar[1].node)
 | 
									yyVAL.node.Ninit = list1(yyDollar[1].node)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			yyVAL.node.Ntest = yyDollar[3].node
 | 
								yyVAL.node.Left = yyDollar[3].node
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case 78:
 | 
						case 78:
 | 
				
			||||||
		yyDollar = yyS[yypt-1 : yypt+1]
 | 
							yyDollar = yyS[yypt-1 : yypt+1]
 | 
				
			||||||
| 
						 | 
					@ -1848,7 +1848,7 @@ yydefault:
 | 
				
			||||||
		yyDollar = yyS[yypt-3 : yypt+1]
 | 
							yyDollar = yyS[yypt-3 : yypt+1]
 | 
				
			||||||
		//line go.y:756
 | 
							//line go.y:756
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if yyDollar[3].node.Ntest == nil {
 | 
								if yyDollar[3].node.Left == nil {
 | 
				
			||||||
				Yyerror("missing condition in if statement")
 | 
									Yyerror("missing condition in if statement")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1886,7 +1886,7 @@ yydefault:
 | 
				
			||||||
		yyDollar = yyS[yypt-5 : yypt+1]
 | 
							yyDollar = yyS[yypt-5 : yypt+1]
 | 
				
			||||||
		//line go.y:788
 | 
							//line go.y:788
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if yyDollar[4].node.Ntest == nil {
 | 
								if yyDollar[4].node.Left == nil {
 | 
				
			||||||
				Yyerror("missing condition in if statement")
 | 
									Yyerror("missing condition in if statement")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			yyDollar[4].node.Nbody = yyDollar[5].list
 | 
								yyDollar[4].node.Nbody = yyDollar[5].list
 | 
				
			||||||
| 
						 | 
					@ -1929,7 +1929,7 @@ yydefault:
 | 
				
			||||||
		//line go.y:822
 | 
							//line go.y:822
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var n *Node
 | 
								var n *Node
 | 
				
			||||||
			n = yyDollar[3].node.Ntest
 | 
								n = yyDollar[3].node.Left
 | 
				
			||||||
			if n != nil && n.Op != OTYPESW {
 | 
								if n != nil && n.Op != OTYPESW {
 | 
				
			||||||
				n = nil
 | 
									n = nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue