cmd/compile: simplify Iter

Passes toolstash -cmp.

Change-Id: I325b02dcc8412ded0dc304d43377c0bdf59c66a8
Reviewed-on: https://go-review.googlesource.com/20405
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go
index e8d8446..ed5b554 100644
--- a/src/cmd/compile/internal/gc/align.go
+++ b/src/cmd/compile/internal/gc/align.go
@@ -295,9 +295,9 @@
 	case TFUNCARGS:
 		t1 := t.Type
 
-		w = widstruct(t.Type, *getthis(t1), 0, 0)
-		w = widstruct(t.Type, *getinarg(t1), w, Widthreg)
-		w = widstruct(t.Type, *Getoutarg(t1), w, Widthreg)
+		w = widstruct(t.Type, getthisx(t1), 0, 0)
+		w = widstruct(t.Type, getinargx(t1), w, Widthreg)
+		w = widstruct(t.Type, getoutargx(t1), w, Widthreg)
 		t1.Argwid = w
 		if w%int64(Widthreg) != 0 {
 			Warn("bad type %v %d\n", t1, w)
@@ -616,27 +616,18 @@
 
 // compute total size of f's in/out arguments.
 func Argsize(t *Type) int {
-	var save Iter
-	var x int64
+	var w int64
 
-	w := int64(0)
-
-	fp := Structfirst(&save, Getoutarg(t))
-	for fp != nil {
-		x = fp.Width + fp.Type.Width
-		if x > w {
+	for fp, ip := IterFields(getoutargx(t)); fp != nil; fp = ip.Next() {
+		if x := fp.Width + fp.Type.Width; x > w {
 			w = x
 		}
-		fp = structnext(&save)
 	}
 
-	fp = funcfirst(&save, t)
-	for fp != nil {
-		x = fp.Width + fp.Type.Width
-		if x > w {
+	for fp, ip := IterParams(t); fp != nil; fp = ip.Next() {
+		if x := fp.Width + fp.Type.Width; x > w {
 			w = x
 		}
-		fp = funcnext(&save)
 	}
 
 	w = (w + int64(Widthptr) - 1) &^ (int64(Widthptr) - 1)
diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
index 7286d39..ee4179d 100644
--- a/src/cmd/compile/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
@@ -1677,8 +1677,7 @@
 			cgen_callinter(n, nil, 0)
 		}
 
-		var flist Iter
-		fp := Structfirst(&flist, Getoutarg(n.Left.Type))
+		fp, _ := IterFields(getoutargx(n.Left.Type))
 		*a = Node{}
 		a.Op = OINDREG
 		a.Reg = int16(Thearch.REGSP)
@@ -2226,8 +2225,7 @@
 			t = t.Type
 		}
 
-		var flist Iter
-		t = Structfirst(&flist, Getoutarg(t))
+		t, _ = IterFields(getoutargx(t))
 		if t != nil {
 			return t.Width + Ctxt.FixedFrameSize()
 		}
@@ -2563,8 +2561,7 @@
 		t = t.Type
 	}
 
-	var flist Iter
-	fp := Structfirst(&flist, Getoutarg(t))
+	fp, _ := IterFields(getoutargx(t))
 	if fp == nil {
 		Fatalf("cgen_callret: nil")
 	}
@@ -2588,8 +2585,7 @@
 		t = t.Type
 	}
 
-	var flist Iter
-	fp := Structfirst(&flist, Getoutarg(t))
+	fp, _ := IterFields(getoutargx(t))
 	if fp == nil {
 		Fatalf("cgen_aret: nil")
 	}
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index a194821..d7f6232 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -548,8 +548,7 @@
 		n = Nod(ONAME, nil, nil)
 		n.Sym = Lookup(".args")
 		n.Type = t
-		var savet Iter
-		first := Structfirst(&savet, &t)
+		first, _ := IterFields(t)
 		if first == nil {
 			Fatalf("nodarg: bad struct")
 		}
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index 9484ab3..8ffc1c7 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -338,8 +338,7 @@
 
 	var l1 []*Node
 	var l2 []*Node
-	var tl Iter
-	for t := Structfirst(&tl, &n.Type); t != nil; t = structnext(&tl) {
+	for t, it := IterFields(n.Type); t != nil; t = it.Next() {
 		tmp := temp(t.Type)
 		l1 = append(l1, tmp)
 		l2 = append(l2, tmp)
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 26c2765..c4773f6 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -377,8 +377,7 @@
 
 	if Curfn.Type.Outnamed {
 		// add clearing of the output parameters
-		var save Iter
-		for t := Structfirst(&save, Getoutarg(Curfn.Type)); t != nil; t = structnext(&save) {
+		for t, it := IterFields(getoutargx(Curfn.Type)); t != nil; t = it.Next() {
 			if t.Nname != nil {
 				n := Nod(OAS, t.Nname, nil)
 				typecheck(&n, Etop)
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index b1745a9..9dc3ce8 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -2407,8 +2407,7 @@
 
 	// Start exit block, find address of result.
 	s.startBlock(bNext)
-	var titer Iter
-	fp := Structfirst(&titer, Getoutarg(n.Left.Type))
+	fp, _ := IterFields(getoutargx(n.Left.Type))
 	if fp == nil || k != callNormal {
 		// call has no return value. Continue with the next statement.
 		return nil
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 5eba252..3246313 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -1892,14 +1892,13 @@
 
 // Given funarg struct list, return list of ODCLFIELD Node fn args.
 func structargs(tl **Type, mustname int) []*Node {
-	var savet Iter
 	var a *Node
 	var n *Node
 	var buf string
 
 	var args []*Node
 	gen := 0
-	for t := Structfirst(&savet, tl); t != nil; t = structnext(&savet) {
+	for t, it := IterFields(*tl); t != nil; t = it.Next() {
 		n = nil
 		if mustname != 0 && (t.Sym == nil || t.Sym.Name == "_") {
 			// invent a name so that we can refer to it in the trampoline
@@ -2250,10 +2249,8 @@
 
 // return nelem of list
 func structcount(t *Type) int {
-	var s Iter
-
 	v := 0
-	for t = Structfirst(&s, &t); t != nil; t = structnext(&s) {
+	for t, it := IterFields(t); t != nil; t = it.Next() {
 		v++
 	}
 	return v
diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go
index 095f814..71fc8b1 100644
--- a/src/cmd/compile/internal/gc/type.go
+++ b/src/cmd/compile/internal/gc/type.go
@@ -164,101 +164,48 @@
 	Lastfn *Node // for usefield
 }
 
-// Iter provides an abstraction for iterating across struct fields
-// and function parameters.
+// Iter provides an abstraction for iterating across struct fields,
+// interface methods, and function parameters.
 type Iter struct {
-	Done  int
-	Tfunc *Type
-	T     *Type
+	a, b *Type
 }
 
-// iterator to walk a structure declaration
-func Structfirst(s *Iter, nn **Type) *Type {
-	var t *Type
-
-	n := *nn
-	if n == nil {
-		goto bad
+// IterFields returns the first field or method in struct or interface type t
+// and an Iter value to continue iterating across the rest.
+func IterFields(t *Type) (*Type, Iter) {
+	if t.Etype != TSTRUCT && t.Etype != TINTER {
+		Fatalf("IterFields: type %v does not have fields", t)
 	}
-
-	switch n.Etype {
-	default:
-		goto bad
-
-	case TSTRUCT, TINTER, TFUNC:
-		break
-	}
-
-	t = n.Type
-	if t == nil {
-		return nil
-	}
-
-	if t.Etype != TFIELD {
-		Fatalf("structfirst: not field %v", t)
-	}
-
-	s.T = t
-	return t
-
-bad:
-	Fatalf("structfirst: not struct %v", n)
-
-	return nil
+	i := Iter{a: t.Type}
+	f := i.Next()
+	return f, i
 }
 
-func structnext(s *Iter) *Type {
-	n := s.T
-	t := n.Down
-	if t == nil {
-		return nil
-	}
-
-	if t.Etype != TFIELD {
-		Fatalf("structnext: not struct %v", n)
-
-		return nil
-	}
-
-	s.T = t
-	return t
-}
-
-// iterator to this and inargs in a function
-func funcfirst(s *Iter, t *Type) *Type {
-	var fp *Type
-
-	if t == nil {
-		goto bad
-	}
-
+// IterParams returns the first reeiver or input parameter in function type t
+// and an Iter value to continue iterating across the rest.
+func IterParams(t *Type) (*Type, Iter) {
 	if t.Etype != TFUNC {
-		goto bad
+		Fatalf("IterParams: type %v does not have params", t)
 	}
-
-	s.Tfunc = t
-	s.Done = 0
-	fp = Structfirst(s, getthis(t))
-	if fp == nil {
-		s.Done = 1
-		fp = Structfirst(s, getinarg(t))
-	}
-
-	return fp
-
-bad:
-	Fatalf("funcfirst: not func %v", t)
-	return nil
+	i := Iter{a: getthisx(t).Type, b: getinargx(t).Type}
+	f := i.Next()
+	return f, i
 }
 
-func funcnext(s *Iter) *Type {
-	fp := structnext(s)
-	if fp == nil && s.Done == 0 {
-		s.Done = 1
-		fp = Structfirst(s, getinarg(s.Tfunc))
+// Next returns the next field, method, or parameter, if any.
+func (i *Iter) Next() *Type {
+	if i.a == nil {
+		if i.b == nil {
+			return nil
+		}
+		i.a, i.b = i.b, nil
 	}
-
-	return fp
+	t := i.a
+	if t.Etype != TFIELD {
+		Fatalf("Iter.Next: type %v is not a field", t)
+	}
+	i.a = t.Down
+	return t
 }
 
 func getthis(t *Type) **Type {
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 2d9627e..44aeef6 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -3371,8 +3371,7 @@
 				goto mismatch
 			}
 			n.Op = OAS2FUNC
-			var s Iter
-			t := Structfirst(&s, &r.Type)
+			t, s := IterFields(r.Type)
 			for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
 				if t.Type != nil && it.N().Type != nil {
 					checkassignto(t.Type, it.N())
@@ -3380,7 +3379,7 @@
 				if it.N().Name != nil && it.N().Name.Defn == n && it.N().Name.Param.Ntype == nil {
 					it.N().Type = t.Type
 				}
-				t = structnext(&s)
+				t = s.Next()
 			}
 
 			goto out
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 81f2e7e..56de81f 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1706,12 +1706,11 @@
 	var l *Node
 	var tmp *Node
 	var a *Node
-	var saver Iter
 
 	// check assign type list to
 	// a expression list. called in
 	//	expr-list = func()
-	r := Structfirst(&saver, nr)
+	r, saver := IterFields(*nr)
 
 	var nn []*Node
 	var mm []*Node
@@ -1723,7 +1722,7 @@
 		}
 		l = it.N()
 		if isblank(l) {
-			r = structnext(&saver)
+			r = saver.Next()
 			continue
 		}
 
@@ -1748,7 +1747,7 @@
 		}
 
 		nn = append(nn, a)
-		r = structnext(&saver)
+		r = saver.Next()
 	}
 
 	if !it.Done() || r != nil {
@@ -1797,12 +1796,10 @@
 
 // helpers for shape errors
 func dumptypes(nl **Type, what string) string {
-	var savel Iter
-
 	fmt_ := ""
 	fmt_ += "\t"
 	first := 1
-	for l := Structfirst(&savel, nl); l != nil; l = structnext(&savel) {
+	for l, it := IterFields(*nl); l != nil; l = it.Next() {
 		if first != 0 {
 			first = 0
 		} else {
@@ -1844,10 +1841,8 @@
 //	return expr-list
 //	func(expr-list)
 func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr []*Node, fp int, init *Nodes) []*Node {
-	var savel Iter
-
 	lr0 := lr
-	l := Structfirst(&savel, nl)
+	l, savel := IterFields(*nl)
 	var r *Node
 	if nodeSeqLen(lr) > 0 {
 		r = nodeSeqFirst(lr)
@@ -1873,7 +1868,7 @@
 		// copy into temporaries.
 		var alist []*Node
 
-		for l := Structfirst(&savel, &r.Type); l != nil; l = structnext(&savel) {
+		for l, it := IterFields(r.Type); l != nil; l = it.Next() {
 			a = temp(l.Type)
 			alist = append(alist, a)
 		}
@@ -1886,13 +1881,13 @@
 		init.Append(a)
 		lr = alist
 		r = nodeSeqFirst(lr)
-		l = Structfirst(&savel, nl)
+		l, savel = IterFields(*nl)
 	}
 
 loop:
 	if l != nil && l.Isddd {
 		// the ddd parameter must be last
-		ll = structnext(&savel)
+		ll = savel.Next()
 
 		if ll != nil {
 			Yyerror("... must be last argument")
@@ -1935,7 +1930,7 @@
 	a = convas(a, init)
 	nn = append(nn, a)
 
-	l = structnext(&savel)
+	l = savel.Next()
 	r = nil
 	lr = lr[1:]
 	if len(lr) > 0 {
@@ -2036,7 +2031,7 @@
 			continue
 		}
 
-		t = *getinarg(on.Type)
+		t = getinargx(on.Type)
 		if t != nil {
 			t = t.Type
 		}
@@ -2590,12 +2585,11 @@
 // generate and return code to allocate
 // copies of escaped parameters to the heap.
 func paramstoheap(argin **Type, out int) []*Node {
-	var savet Iter
 	var v *Node
 	var as *Node
 
 	var nn []*Node
-	for t := Structfirst(&savet, argin); t != nil; t = structnext(&savet) {
+	for t, it := IterFields(*argin); t != nil; t = it.Next() {
 		v = t.Nname
 		if v != nil && v.Sym != nil && v.Sym.Name[0] == '~' && v.Sym.Name[1] == 'r' { // unnamed result
 			v = nil
@@ -2636,11 +2630,10 @@
 
 // walk through argout parameters copying back to stack
 func returnsfromheap(argin **Type) []*Node {
-	var savet Iter
 	var v *Node
 
 	var nn []*Node
-	for t := Structfirst(&savet, argin); t != nil; t = structnext(&savet) {
+	for t, it := IterFields(*argin); t != nil; t = it.Next() {
 		v = t.Nname
 		if v == nil || v.Class != PHEAP|PPARAMOUT {
 			continue