cmd/compile: change get{this,inarg,outarg}x? into methods

More idiomatic naming (in particular, matches the naming used for
go/types.Signature).

Also, convert more code to use these methods and/or IterFields.
(Still more to go; only made a quick pass for low hanging fruit.)

Passes toolstash -cmp.

Change-Id: I61831bfb1ec2cd50d4c7efc6062bca4e0dcf267b
Reviewed-on: https://go-review.googlesource.com/20451
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go
index ed5b554..e11da50 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, getthisx(t1), 0, 0)
-		w = widstruct(t.Type, getinargx(t1), w, Widthreg)
-		w = widstruct(t.Type, getoutargx(t1), w, Widthreg)
+		w = widstruct(t.Type, t1.Recv(), 0, 0)
+		w = widstruct(t.Type, t1.Params(), w, Widthreg)
+		w = widstruct(t.Type, t1.Results(), w, Widthreg)
 		t1.Argwid = w
 		if w%int64(Widthreg) != 0 {
 			Warn("bad type %v %d\n", t1, w)
@@ -618,7 +618,7 @@
 func Argsize(t *Type) int {
 	var w int64
 
-	for fp, ip := IterFields(getoutargx(t)); fp != nil; fp = ip.Next() {
+	for fp, ip := IterFields(t.Results()); fp != nil; fp = ip.Next() {
 		if x := fp.Width + fp.Type.Width; x > w {
 			w = x
 		}
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index 36486e1..d0bb56a 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -477,9 +477,9 @@
 
 		for _, m := range methods {
 			p.string(m.Sym.Name)
-			p.paramList(getthisx(m.Type))
-			p.paramList(getinargx(m.Type))
-			p.paramList(getoutargx(m.Type))
+			p.paramList(m.Type.Recv())
+			p.paramList(m.Type.Params())
+			p.paramList(m.Type.Results())
 			p.inlinedBody(m.Type.Nname)
 
 			if p.trace && m.Down != nil {
@@ -521,8 +521,8 @@
 
 	case TFUNC:
 		p.tag(signatureTag)
-		p.paramList(getinargx(t))
-		p.paramList(getoutargx(t))
+		p.paramList(t.Params())
+		p.paramList(t.Results())
 
 	case TINTER:
 		p.tag(interfaceTag)
@@ -609,8 +609,8 @@
 	// TODO(gri) For functions signatures, we use p.typ() to export
 	// so we could share the same type with multiple functions. Do
 	// the same here, or never try to do this for functions.
-	p.paramList(getinargx(m.Type))
-	p.paramList(getoutargx(m.Type))
+	p.paramList(m.Type.Params())
+	p.paramList(m.Type.Results())
 }
 
 // fieldName is like qualifiedName but it doesn't record the package
diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
index ee4179d..c9d4897 100644
--- a/src/cmd/compile/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
@@ -1677,7 +1677,7 @@
 			cgen_callinter(n, nil, 0)
 		}
 
-		fp, _ := IterFields(getoutargx(n.Left.Type))
+		fp, _ := IterFields(n.Left.Type.Results())
 		*a = Node{}
 		a.Op = OINDREG
 		a.Reg = int16(Thearch.REGSP)
@@ -2225,7 +2225,7 @@
 			t = t.Type
 		}
 
-		t, _ = IterFields(getoutargx(t))
+		t, _ = IterFields(t.Results())
 		if t != nil {
 			return t.Width + Ctxt.FixedFrameSize()
 		}
@@ -2561,7 +2561,7 @@
 		t = t.Type
 	}
 
-	fp, _ := IterFields(getoutargx(t))
+	fp, _ := IterFields(t.Results())
 	if fp == nil {
 		Fatalf("cgen_callret: nil")
 	}
@@ -2585,7 +2585,7 @@
 		t = t.Type
 	}
 
-	fp, _ := IterFields(getoutargx(t))
+	fp, _ := IterFields(t.Results())
 	if fp == nil {
 		Fatalf("cgen_aret: nil")
 	}
diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go
index 3a2ce72..d040bdc 100644
--- a/src/cmd/compile/internal/gc/closure.go
+++ b/src/cmd/compile/internal/gc/closure.go
@@ -299,7 +299,7 @@
 
 		// Get pointer to input arguments.
 		// We are going to insert captured variables before input args.
-		param := &getinargx(f.Type).Type
+		param := &f.Type.Params().Type
 		original_args := *param // old input args
 		original_dcl := xfunc.Func.Dcl
 		xfunc.Func.Dcl = nil
@@ -535,7 +535,7 @@
 	Curfn = xfunc
 	var fld *Node
 	var n *Node
-	for t := getinargx(t0).Type; t != nil; t = t.Down {
+	for t, it := IterFields(t0.Params()); t != nil; t = it.Next() {
 		n = newname(Lookupf("a%d", i))
 		i++
 		n.Class = PPARAM
@@ -554,7 +554,7 @@
 	i = 0
 	l = nil
 	var retargs []*Node
-	for t := getoutargx(t0).Type; t != nil; t = t.Down {
+	for t, it := IterFields(t0.Results()); t != nil; t = it.Next() {
 		n = newname(Lookupf("r%d", i))
 		i++
 		n.Class = PPARAMOUT
diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index b5ae6dc..22ab3cc 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -664,36 +664,33 @@
 	}
 
 	if t.Thistuple != 0 {
-		var n *Node
-		for ft := getthisx(t).Type; ft != nil; ft = ft.Down {
+		for ft, it := IterFields(t.Recv()); ft != nil; ft = it.Next() {
 			if ft.Nname == nil || ft.Nname.Sym == nil {
 				continue
 			}
-			n = ft.Nname // no need for newname(ft->nname->sym)
+			n := ft.Nname // no need for newname(ft->nname->sym)
 			n.Type = ft.Type
 			declare(n, PPARAM)
 		}
 	}
 
 	if t.Intuple != 0 {
-		var n *Node
-		for ft := getinargx(t).Type; ft != nil; ft = ft.Down {
+		for ft, it := IterFields(t.Params()); ft != nil; ft = it.Next() {
 			if ft.Nname == nil || ft.Nname.Sym == nil {
 				continue
 			}
-			n = ft.Nname
+			n := ft.Nname
 			n.Type = ft.Type
 			declare(n, PPARAM)
 		}
 	}
 
 	if t.Outtuple != 0 {
-		var n *Node
-		for ft := getoutargx(t).Type; ft != nil; ft = ft.Down {
+		for ft, it := IterFields(t.Results()); ft != nil; ft = it.Next() {
 			if ft.Nname == nil || ft.Nname.Sym == nil {
 				continue
 			}
-			n = ft.Nname
+			n := ft.Nname
 			n.Type = ft.Type
 			declare(n, PPARAMOUT)
 		}
@@ -1139,7 +1136,7 @@
 // Those methods have an anonymous *struct{} as the receiver.
 // (See fakethis above.)
 func isifacemethod(f *Type) bool {
-	rcvr := getthisx(f).Type
+	rcvr := f.Recv().Type
 	if rcvr.Sym != nil {
 		return false
 	}
@@ -1170,16 +1167,16 @@
 	if this != nil {
 		rcvr = []*Node{this}
 	}
-	t.Type = tofunargs(rcvr)
-	t.Type.Down = tofunargs(out)
-	t.Type.Down.Down = tofunargs(in)
+	*t.RecvP() = tofunargs(rcvr)
+	*t.ResultsP() = tofunargs(out)
+	*t.ParamsP() = tofunargs(in)
 
 	uniqgen++
-	checkdupfields(t.Type.Type, "argument")
-	checkdupfields(t.Type.Down.Type, "argument")
-	checkdupfields(t.Type.Down.Down.Type, "argument")
+	checkdupfields(t.Recv().Type, "argument")
+	checkdupfields(t.Results().Type, "argument")
+	checkdupfields(t.Params().Type, "argument")
 
-	if t.Type.Broke || t.Type.Down.Broke || t.Type.Down.Down.Broke {
+	if t.Recv().Broke || t.Results().Broke || t.Params().Broke {
 		t.Broke = true
 	}
 
@@ -1311,7 +1308,7 @@
 	}
 
 	// get parent type sym
-	pa := getthisx(t).Type // ptr to this structure
+	pa := t.Recv().Type // ptr to this structure
 	if pa == nil {
 		Yyerror("missing receiver")
 		return
diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index 1779579..5dc4348 100644
--- a/src/cmd/compile/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -1321,7 +1321,7 @@
 	i := 0
 	nE := e.nodeEscState(n)
 	nE.Escretval.Set(nil) // Suspect this is not nil for indirect calls.
-	for t := getoutargx(fntype).Type; t != nil; t = t.Down {
+	for t, it := IterFields(fntype.Results()); t != nil; t = it.Next() {
 		src := Nod(ONAME, nil, nil)
 		buf := fmt.Sprintf(".out%d", i)
 		i++
@@ -1389,7 +1389,7 @@
 		initEscretval(e, n, fntype)
 		// If there is a receiver, it also leaks to heap.
 		if n.Op != OCALLFUNC {
-			t := getthisx(fntype).Type
+			t := fntype.Recv().Type
 			src := n.Left.Left
 			if haspointers(t.Type) {
 				escassign(e, &e.theSink, src)
@@ -1473,7 +1473,7 @@
 
 	// Receiver.
 	if n.Op != OCALLFUNC {
-		t := getthisx(fntype).Type
+		t := fntype.Recv().Type
 		src := n.Left.Left
 		if haspointers(t.Type) {
 			escassignfromtag(e, t.Note, nE.Escretval, src)
@@ -1482,7 +1482,7 @@
 
 	var src *Node
 	it := nodeSeqIterate(ll)
-	for t := getinargx(fntype).Type; !it.Done(); it.Next() {
+	for t := fntype.Params().Type; !it.Done(); it.Next() {
 		src = it.N()
 		if t.Isddd && !n.Isddd {
 			// Introduce ODDDARG node to represent ... allocation.
@@ -1843,7 +1843,7 @@
 	// unless //go:noescape is given before the declaration.
 	if len(func_.Nbody.Slice()) == 0 {
 		if func_.Noescape {
-			for t := getinargx(func_.Type).Type; t != nil; t = t.Down {
+			for t, it := IterFields(func_.Type.Params()); t != nil; t = it.Next() {
 				if haspointers(t.Type) {
 					t.Note = mktag(EscNone)
 				}
@@ -1857,7 +1857,7 @@
 		// but we are reusing the ability to annotate an individual function
 		// argument and pass those annotations along to importing code.
 		narg := 0
-		for t := getinargx(func_.Type).Type; t != nil; t = t.Down {
+		for t, it := IterFields(func_.Type.Params()); t != nil; t = it.Next() {
 			narg++
 			if t.Type.Etype == TUINTPTR {
 				if Debug['m'] != 0 {
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 1896e33..5c53da3 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -314,10 +314,10 @@
 			if Debug['l'] < 2 {
 				typecheckinl(f.Type.Nname)
 			}
-			exportf("\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
+			exportf("\tfunc (%v) %v %v { %v }\n", Tconv(f.Type.Recv().Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
 			reexportdeplist(f.Type.Nname.Func.Inl)
 		} else {
-			exportf("\tfunc (%v) %v %v\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
+			exportf("\tfunc (%v) %v %v\n", Tconv(f.Type.Recv().Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
 		}
 	}
 }
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index b712f4c..ac1d8cb 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -615,12 +615,12 @@
 		} else {
 			if t.Thistuple != 0 {
 				buf.WriteString("method")
-				buf.WriteString(Tconv(getthisx(t), 0))
+				buf.WriteString(Tconv(t.Recv(), 0))
 				buf.WriteString(" ")
 			}
 			buf.WriteString("func")
 		}
-		buf.WriteString(Tconv(getinargx(t), 0))
+		buf.WriteString(Tconv(t.Params(), 0))
 
 		switch t.Outtuple {
 		case 0:
@@ -629,14 +629,14 @@
 		case 1:
 			if fmtmode != FExp {
 				buf.WriteString(" ")
-				buf.WriteString(Tconv(getoutargx(t).Type.Type, 0)) // struct->field->field's type
+				buf.WriteString(Tconv(t.Results().Type.Type, 0)) // struct->field->field's type
 				break
 			}
 			fallthrough
 
 		default:
 			buf.WriteString(" ")
-			buf.WriteString(Tconv(getoutargx(t), 0))
+			buf.WriteString(Tconv(t.Results(), 0))
 		}
 		return buf.String()
 
diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go
index e3c1e4a..c30d0e0 100644
--- a/src/cmd/compile/internal/gc/gen.go
+++ b/src/cmd/compile/internal/gc/gen.go
@@ -440,7 +440,7 @@
 		r1.Type = byteptr
 		r2.Type = byteptr
 		setNodeSeq(&call.List, list(list(list1(&r1), &r2), typename(n.Left.Type)))
-		setNodeSeq(&call.List, ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List.Slice(), 0, nil))
+		setNodeSeq(&call.List, ascompatte(OCALLFUNC, call, false, fn.Type.ParamsP(), call.List.Slice(), 0, nil))
 		gen(call)
 		Regfree(&r1)
 		Regfree(&r2)
@@ -526,7 +526,7 @@
 	dowidth(fn.Type)
 	call := Nod(OCALLFUNC, fn, nil)
 	setNodeSeq(&call.List, list(list(list1(&r1), &r2), typename(n.Left.Type)))
-	setNodeSeq(&call.List, ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List.Slice(), 0, nil))
+	setNodeSeq(&call.List, ascompatte(OCALLFUNC, call, false, fn.Type.ParamsP(), call.List.Slice(), 0, nil))
 	gen(call)
 	Regfree(&r1)
 	Regfree(&r2)
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index ac93c6b..c2faff7 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -48,7 +48,7 @@
 func fnpkg(fn *Node) *Pkg {
 	if fn.Type.Thistuple != 0 {
 		// method
-		rcvr := getthisx(fn.Type).Type.Type
+		rcvr := fn.Type.Recv().Type.Type
 
 		if Isptr[rcvr.Etype] {
 			rcvr = rcvr.Type
@@ -122,7 +122,7 @@
 
 	// can't handle ... args yet
 	if Debug['l'] < 3 {
-		for t := fn.Type.Type.Down.Down.Type; t != nil; t = t.Down {
+		for t, it := IterFields(fn.Type.Params()); t != nil; t = it.Next() {
 			if t.Isddd {
 				return
 			}
@@ -592,7 +592,7 @@
 
 	// temporaries for return values.
 	var m *Node
-	for t := getoutargx(fn.Type).Type; t != nil; t = t.Down {
+	for t, it := IterFields(fn.Type.Results()); t != nil; t = it.Next() {
 		if t != nil && t.Nname != nil && !isblank(t.Nname) {
 			m = inlvar(t.Nname)
 			typecheck(&m, Erv)
@@ -611,7 +611,7 @@
 	var as *Node
 	if fn.Type.Thistuple != 0 && n.Left.Op == ODOTMETH {
 		// method call with a receiver.
-		t := getthisx(fn.Type).Type
+		t := fn.Type.Recv().Type
 
 		if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Name.Inlvar == nil {
 			Fatalf("missing inlvar for %v\n", t.Nname)
@@ -634,7 +634,7 @@
 
 	var varargtype *Type
 	varargcount := 0
-	for t := fn.Type.Type.Down.Down.Type; t != nil; t = t.Down {
+	for t, it := IterFields(fn.Type.Params()); t != nil; t = it.Next() {
 		if t.Isddd {
 			variadic = true
 			varargtype = t.Type
@@ -680,7 +680,7 @@
 		}
 
 		// append receiver inlvar to LHS.
-		t := getthisx(fn.Type).Type
+		t := fn.Type.Recv().Type
 
 		if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Name.Inlvar == nil {
 			Fatalf("missing inlvar for %v\n", t.Nname)
@@ -700,7 +700,7 @@
 	if !chkargcount {
 		// 0 or 1 expression on RHS.
 		var i int
-		for t := getinargx(fn.Type).Type; t != nil; t = t.Down {
+		for t, it2 := IterFields(fn.Type.Params()); t != nil; t = it2.Next() {
 			if variadic && t.Isddd {
 				vararg = tinlvar(t)
 				for i = 0; i < varargcount && it.Len() != 0; i++ {
@@ -717,7 +717,7 @@
 	} else {
 		// match arguments except final variadic (unless the call is dotted itself)
 		var t *Type
-		for t = getinargx(fn.Type).Type; t != nil; {
+		for t = fn.Type.Params().Type; t != nil; {
 			if it.Done() {
 				break
 			}
@@ -746,7 +746,7 @@
 		}
 
 		if !it.Done() || t != nil {
-			Fatalf("arg count mismatch: %v  vs %v\n", Tconv(getinargx(fn.Type), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
+			Fatalf("arg count mismatch: %v  vs %v\n", Tconv(fn.Type.Params(), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
 		}
 	}
 
diff --git a/src/cmd/compile/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go
index 9261406..9a6e110 100644
--- a/src/cmd/compile/internal/gc/lex.go
+++ b/src/cmd/compile/internal/gc/lex.go
@@ -2193,9 +2193,9 @@
 	out.Type.Type = Types[TSTRING]
 	out.Funarg = true
 	f := typ(TFUNC)
-	*getthis(f) = rcvr
-	*Getoutarg(f) = out
-	*getinarg(f) = in
+	*f.RecvP() = rcvr
+	*f.ResultsP() = out
+	*f.ParamsP() = in
 	f.Thistuple = 1
 	f.Intuple = 0
 	f.Outnamed = false
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index 8ffc1c7..7f74082 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -375,7 +375,7 @@
 	setNodeSeq(&n.List, ordercallargs(n.List, order))
 
 	if n.Op == OCALLFUNC {
-		t := getinargx(n.Left.Type).Type
+		t := n.Left.Type.Params().Type
 		for it := nodeSeqIterate(n.List); !it.Done() && t != nil; it.Next() {
 			// Check for "unsafe-uintptr" tag provided by escape analysis.
 			// If present and the argument is really a pointer being converted
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index c4773f6..607d068 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -155,12 +155,12 @@
 	var xoffset int64
 	if Curfn.Type.Thistuple > 0 {
 		xoffset = 0
-		onebitwalktype1(getthisx(Curfn.Type), &xoffset, bv)
+		onebitwalktype1(Curfn.Type.Recv(), &xoffset, bv)
 	}
 
 	if Curfn.Type.Intuple > 0 {
 		xoffset = 0
-		onebitwalktype1(getinargx(Curfn.Type), &xoffset, bv)
+		onebitwalktype1(Curfn.Type.Params(), &xoffset, bv)
 	}
 
 	for j := 0; int32(j) < bv.n; j += 32 {
@@ -168,7 +168,7 @@
 	}
 	if Curfn.Type.Outtuple > 0 {
 		xoffset = 0
-		onebitwalktype1(getoutargx(Curfn.Type), &xoffset, bv)
+		onebitwalktype1(Curfn.Type.Results(), &xoffset, bv)
 		for j := 0; int32(j) < bv.n; j += 32 {
 			off = duint32(sym, off, bv.b[j/32])
 		}
@@ -377,7 +377,7 @@
 
 	if Curfn.Type.Outnamed {
 		// add clearing of the output parameters
-		for t, it := IterFields(getoutargx(Curfn.Type)); t != nil; t = it.Next() {
+		for t, it := IterFields(Curfn.Type.Results()); 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/plive.go b/src/cmd/compile/internal/gc/plive.go
index e710478..34bd2a6 100644
--- a/src/cmd/compile/internal/gc/plive.go
+++ b/src/cmd/compile/internal/gc/plive.go
@@ -1003,14 +1003,14 @@
 	// If the receiver or arguments are unnamed, they will be omitted
 	// from the list above. Preserve those values - even though they are unused -
 	// in order to keep their addresses live for use in stack traces.
-	thisargtype := getthisx(lv.fn.Type)
+	thisargtype := lv.fn.Type.Recv()
 
 	if thisargtype != nil {
 		xoffset = 0
 		onebitwalktype1(thisargtype, &xoffset, args)
 	}
 
-	inargtype := getinargx(lv.fn.Type)
+	inargtype := lv.fn.Type.Params()
 	if inargtype != nil {
 		xoffset = 0
 		onebitwalktype1(inargtype, &xoffset, args)
diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go
index a7cf888..43447b459 100644
--- a/src/cmd/compile/internal/gc/range.go
+++ b/src/cmd/compile/internal/gc/range.go
@@ -298,7 +298,7 @@
 			a = Nod(OAS2, nil, nil)
 			setNodeSeq(&a.List, []*Node{hv1, hv2})
 			fn := syslook("stringiter2")
-			setNodeSeq(&a.Rlist, []*Node{mkcall1(fn, getoutargx(fn.Type), nil, ha, hv1)})
+			setNodeSeq(&a.Rlist, []*Node{mkcall1(fn, fn.Type.Results(), nil, ha, hv1)})
 		}
 
 		n.Left = Nod(ONE, hv1, Nodintconst(0))
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index b234333..b83e2ad 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -255,7 +255,7 @@
 	}
 
 	var d *Node
-	for t := getinargx(f).Type; t != nil; t = t.Down {
+	for t, it := IterFields(f.Params()); t != nil; t = it.Next() {
 		d = Nod(ODCLFIELD, nil, nil)
 		d.Type = t.Type
 		d.Isddd = t.Isddd
@@ -263,7 +263,7 @@
 	}
 
 	var out []*Node
-	for t := getoutargx(f).Type; t != nil; t = t.Down {
+	for t, it := IterFields(f.Results()); t != nil; t = it.Next() {
 		d = Nod(ODCLFIELD, nil, nil)
 		d.Type = t.Type
 		out = append(out, d)
@@ -306,7 +306,7 @@
 		if f.Type.Etype != TFUNC || f.Type.Thistuple == 0 {
 			Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
 		}
-		if getthisx(f.Type).Type == nil {
+		if f.Type.Recv().Type == nil {
 			Fatalf("receiver with no type on %v method %v %v\n", mt, f.Sym, f)
 		}
 		if f.Nointerface {
@@ -322,7 +322,7 @@
 		// if pointer receiver but non-pointer t and
 		// this is not an embedded pointer inside a struct,
 		// method does not apply.
-		this := getthisx(f.Type).Type.Type
+		this := f.Type.Recv().Type.Type
 
 		if Isptr[this.Etype] && this.Type == t {
 			continue
@@ -373,7 +373,7 @@
 // imethods returns the methods of the interface type t, sorted by name.
 func imethods(t *Type) []*Sig {
 	var methods []*Sig
-	for f := t.Type; f != nil; f = f.Down {
+	for f, it := IterFields(t); f != nil; f = it.Next() {
 		if f.Etype != TFIELD {
 			Fatalf("imethods: not field")
 		}
@@ -612,7 +612,7 @@
 
 	case TSTRUCT:
 		ret = false
-		for t1 := t.Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
 			if haspointers(t1.Type) {
 				ret = true
 				break
@@ -675,7 +675,7 @@
 	case TSTRUCT:
 		// Find the last field that has pointers.
 		var lastPtrField *Type
-		for t1 := t.Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
 			if haspointers(t1.Type) {
 				lastPtrField = t1
 			}
@@ -906,7 +906,7 @@
 		return isreflexive(t.Type)
 
 	case TSTRUCT:
-		for t1 := t.Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
 			if !isreflexive(t1.Type) {
 				return false
 			}
@@ -956,7 +956,7 @@
 		return needkeyupdate(t.Type)
 
 	case TSTRUCT:
-		for t1 := t.Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
 			if needkeyupdate(t1.Type) {
 				return true
 			}
@@ -1051,15 +1051,15 @@
 		ot = dextratype(s, ot, t, 0)
 
 	case TFUNC:
-		for t1 := getthisx(t).Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t.Recv()); t1 != nil; t1 = it.Next() {
 			dtypesym(t1.Type)
 		}
 		isddd := false
-		for t1 := getinargx(t).Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t.Params()); t1 != nil; t1 = it.Next() {
 			isddd = t1.Isddd
 			dtypesym(t1.Type)
 		}
-		for t1 := getoutargx(t).Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t.Results()); t1 != nil; t1 = it.Next() {
 			dtypesym(t1.Type)
 		}
 
@@ -1079,13 +1079,13 @@
 		ot = dextratype(s, ot, t, dataAdd)
 
 		// Array of rtype pointers follows funcType.
-		for t1 := getthisx(t).Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t.Recv()); t1 != nil; t1 = it.Next() {
 			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
 		}
-		for t1 := getinargx(t).Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t.Params()); t1 != nil; t1 = it.Next() {
 			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
 		}
-		for t1 := getoutargx(t).Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t.Results()); t1 != nil; t1 = it.Next() {
 			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
 		}
 
@@ -1166,7 +1166,7 @@
 	case TSTRUCT:
 		n := 0
 
-		for t1 := t.Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
 			dtypesym(t1.Type)
 			n++
 		}
@@ -1179,8 +1179,8 @@
 		dataAdd := n * structfieldSize()
 		ot = dextratype(s, ot, t, dataAdd)
 
-		for t1 := t.Type; t1 != nil; t1 = t1.Down {
-			// ../../../../runtime/type.go:/structfield
+		for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
+			// ../../../../runtime/type.go:/structField
 			if t1.Sym != nil && t1.Embedded == 0 {
 				ot = dgostringptr(s, ot, t1.Sym.Name)
 				if exportname(t1.Sym.Name) {
@@ -1547,7 +1547,7 @@
 		p.w.Repeat(elem.Width/int64(Widthptr), count-1)
 
 	case TSTRUCT:
-		for t1 := t.Type; t1 != nil; t1 = t1.Down {
+		for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
 			p.emit(t1.Type, offset+t1.Width)
 		}
 	}
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 9dc3ce8..8027a90 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -2407,7 +2407,7 @@
 
 	// Start exit block, find address of result.
 	s.startBlock(bNext)
-	fp, _ := IterFields(getoutargx(n.Left.Type))
+	fp, _ := IterFields(n.Left.Type.Results())
 	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 3246313..4d4be84 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -431,7 +431,7 @@
 	}
 
 	var a []*Type
-	for f := t.Type; f != nil; f = f.Down {
+	for f, it := IterFields(t); f != nil; f = it.Next() {
 		a = append(a, f)
 	}
 	sort.Sort(methcmp(a))
@@ -767,34 +767,20 @@
 
 		// Loop over structs: receiver, in, out.
 	case TFUNC:
-		t1 = t1.Type
-		t2 = t2.Type
-		for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
-			if t1.Etype != TSTRUCT || t2.Etype != TSTRUCT {
-				Fatalf("func missing struct: %v %v", t1, t2)
-			}
-
+		for _, f := range [...]func(*Type) *Type{(*Type).Recv, (*Type).Results, (*Type).Params} {
 			// Loop over fields in structs, ignoring argument names.
-			ta := t1.Type
-			tb := t2.Type
-			for ; ta != nil && tb != nil; ta, tb = ta.Down, tb.Down {
-				if ta.Etype != TFIELD || tb.Etype != TFIELD {
-					Fatalf("func struct missing field: %v %v", ta, tb)
-				}
+			ta, ia := IterFields(f(t1))
+			tb, ib := IterFields(f(t2))
+			for ; ta != nil && tb != nil; ta, tb = ia.Next(), ib.Next() {
 				if ta.Isddd != tb.Isddd || !eqtype1(ta.Type, tb.Type, assumedEqual) {
 					return false
 				}
 			}
-
 			if ta != nil || tb != nil {
 				return false
 			}
 		}
-
-		if t1 == nil && t2 == nil {
-			return true
-		}
-		return false
+		return true
 
 	case TARRAY:
 		if t1.Bound != t2.Bound {
@@ -1154,9 +1140,9 @@
 			continue
 
 		case TFUNC:
-			substAny(&t.Type, types)
-			substAny(&t.Type.Down.Down, types)
-			substAny(&t.Type.Down, types)
+			substAny(t.RecvP(), types)
+			substAny(t.ParamsP(), types)
+			substAny(t.ResultsP(), types)
 
 		case TSTRUCT:
 			for t = t.Type; t != nil; t = t.Down {
@@ -1245,9 +1231,9 @@
 
 	case TFUNC:
 		nt = shallow(t)
-		nt.Type = deep(t.Type)
-		nt.Type.Down = deep(t.Type.Down)
-		nt.Type.Down.Down = deep(t.Type.Down.Down)
+		*nt.RecvP() = deep(t.Recv())
+		*nt.ResultsP() = deep(t.Results())
+		*nt.ParamsP() = deep(t.Params())
 
 	case TSTRUCT:
 		nt = shallow(t)
@@ -1963,8 +1949,8 @@
 
 	this := Nod(ODCLFIELD, newname(Lookup(".this")), typenod(rcvr))
 	this.Left.Name.Param.Ntype = this.Right
-	in := structargs(getinarg(method.Type), 1)
-	out := structargs(Getoutarg(method.Type), 0)
+	in := structargs(method.Type.ParamsP(), 1)
+	out := structargs(method.Type.ResultsP(), 0)
 
 	t := Nod(OTFUNC, nil, nil)
 	l := []*Node{this}
@@ -2001,7 +1987,7 @@
 		isddd = n.Left.Isddd
 	}
 
-	methodrcvr := getthisx(method.Type).Type.Type
+	methodrcvr := method.Type.Recv().Type.Type
 
 	// generate nil pointer check for better error
 	if Isptr[rcvr.Etype] && rcvr.Type == methodrcvr {
@@ -2190,7 +2176,7 @@
 
 		// if pointer receiver in method,
 		// the method does not exist for value types.
-		rcvr = getthisx(tm.Type).Type.Type
+		rcvr = tm.Type.Recv().Type.Type
 
 		if Isptr[rcvr.Etype] && !Isptr[t0.Etype] && !followptr && !isifacemethod(tm.Type) {
 			if false && Debug['r'] != 0 {
diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go
index 71fc8b1..b18da81 100644
--- a/src/cmd/compile/internal/gc/type.go
+++ b/src/cmd/compile/internal/gc/type.go
@@ -187,7 +187,7 @@
 	if t.Etype != TFUNC {
 		Fatalf("IterParams: type %v does not have params", t)
 	}
-	i := Iter{a: getthisx(t).Type, b: getinargx(t).Type}
+	i := Iter{a: t.Recv().Type, b: t.Params().Type}
 	f := i.Next()
 	return f, i
 }
@@ -208,38 +208,30 @@
 	return t
 }
 
-func getthis(t *Type) **Type {
-	if t.Etype != TFUNC {
-		Fatalf("getthis: not a func %v", t)
+func (t *Type) wantEtype(et EType) {
+	if t.Etype != et {
+		Fatalf("want %v, but have %v", et, t)
 	}
+}
+
+func (t *Type) RecvP() **Type {
+	t.wantEtype(TFUNC)
 	return &t.Type
 }
 
-func Getoutarg(t *Type) **Type {
-	if t.Etype != TFUNC {
-		Fatalf("getoutarg: not a func %v", t)
-	}
-	return &t.Type.Down
-}
-
-func getinarg(t *Type) **Type {
-	if t.Etype != TFUNC {
-		Fatalf("getinarg: not a func %v", t)
-	}
+func (t *Type) ParamsP() **Type {
+	t.wantEtype(TFUNC)
 	return &t.Type.Down.Down
 }
 
-func getthisx(t *Type) *Type {
-	return *getthis(t)
+func (t *Type) ResultsP() **Type {
+	t.wantEtype(TFUNC)
+	return &t.Type.Down
 }
 
-func getoutargx(t *Type) *Type {
-	return *Getoutarg(t)
-}
-
-func getinargx(t *Type) *Type {
-	return *getinarg(t)
-}
+func (t *Type) Recv() *Type    { return *t.RecvP() }
+func (t *Type) Params() *Type  { return *t.ParamsP() }
+func (t *Type) Results() *Type { return *t.ResultsP() }
 
 func (t *Type) Size() int64 {
 	dowidth(t)
@@ -408,14 +400,11 @@
 
 		fallthrough
 	case TINTER:
-		t1 := t.Type
-		x1 := x.Type
-		for ; t1 != nil && x1 != nil; t1, x1 = t1.Down, x1.Down {
+		t1, ti := IterFields(t)
+		x1, xi := IterFields(x)
+		for ; t1 != nil && x1 != nil; t1, x1 = ti.Next(), xi.Next() {
 			if t1.Embedded != x1.Embedded {
-				if t1.Embedded < x1.Embedded {
-					return ssa.CMPlt
-				}
-				return ssa.CMPgt
+				return cmpForNe(t1.Embedded < x1.Embedded)
 			}
 			if t1.Note != x1.Note {
 				if t1.Note == nil {
@@ -425,62 +414,38 @@
 					return ssa.CMPgt
 				}
 				if *t1.Note != *x1.Note {
-					if *t1.Note < *x1.Note {
-						return ssa.CMPlt
-					}
-					return ssa.CMPgt
+					return cmpForNe(*t1.Note < *x1.Note)
 				}
 			}
-			c := t1.Sym.cmpsym(x1.Sym)
-			if c != ssa.CMPeq {
+			if c := t1.Sym.cmpsym(x1.Sym); c != ssa.CMPeq {
 				return c
 			}
-			c = t1.Type.cmp(x1.Type)
-			if c != ssa.CMPeq {
+			if c := t1.Type.cmp(x1.Type); c != ssa.CMPeq {
 				return c
 			}
 		}
-		if t1 == x1 {
-			return ssa.CMPeq
+		if t1 != x1 {
+			return cmpForNe(t1 == nil)
 		}
-		if t1 == nil {
-			return ssa.CMPlt
-		}
-		return ssa.CMPgt
+		return ssa.CMPeq
 
 	case TFUNC:
-		t1 := t.Type
-		t2 := x.Type
-		for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
+		for _, f := range [...]func(*Type) *Type{(*Type).Recv, (*Type).Results, (*Type).Params} {
 			// Loop over fields in structs, ignoring argument names.
-			ta := t1.Type
-			tb := t2.Type
-			for ; ta != nil && tb != nil; ta, tb = ta.Down, tb.Down {
+			ta, ia := IterFields(f(t))
+			tb, ib := IterFields(f(x))
+			for ; ta != nil && tb != nil; ta, tb = ia.Next(), ib.Next() {
 				if ta.Isddd != tb.Isddd {
-					if ta.Isddd {
-						return ssa.CMPgt
-					}
-					return ssa.CMPlt
+					return cmpForNe(!ta.Isddd)
 				}
-				c := ta.Type.cmp(tb.Type)
-				if c != ssa.CMPeq {
+				if c := ta.Type.cmp(tb.Type); c != ssa.CMPeq {
 					return c
 				}
 			}
-
 			if ta != tb {
-				if t1 == nil {
-					return ssa.CMPlt
-				}
-				return ssa.CMPgt
+				return cmpForNe(ta == nil)
 			}
 		}
-		if t1 != t2 {
-			if t1 == nil {
-				return ssa.CMPlt
-			}
-			return ssa.CMPgt
-		}
 		return ssa.CMPeq
 
 	case TARRAY:
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 44aeef6..85605dc 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -1312,7 +1312,7 @@
 			// information further down the call chain to know if we
 			// were testing a method receiver for unexported fields.
 			// It isn't necessary, so just do a sanity check.
-			tp := getthisx(t).Type.Type
+			tp := t.Recv().Type.Type
 
 			if l.Left == nil || !Eqtype(l.Left.Type, tp) {
 				Fatalf("method receiver")
@@ -1327,14 +1327,14 @@
 			}
 		}
 
-		typecheckaste(OCALL, n.Left, n.Isddd, getinargx(t), n.List, func() string { return fmt.Sprintf("argument to %v", n.Left) })
+		typecheckaste(OCALL, n.Left, n.Isddd, t.Params(), n.List, func() string { return fmt.Sprintf("argument to %v", n.Left) })
 		ok |= Etop
 		if t.Outtuple == 0 {
 			break OpSwitch
 		}
 		ok |= Erv
 		if t.Outtuple == 1 {
-			t := getoutargx(l.Type).Type
+			t := l.Type.Results().Type
 			if t == nil {
 				n.Type = nil
 				return
@@ -1363,7 +1363,7 @@
 			break OpSwitch
 		}
 
-		n.Type = getoutargx(l.Type)
+		n.Type = l.Type.Results()
 
 		break OpSwitch
 
@@ -2107,7 +2107,7 @@
 		if Curfn.Type.Outnamed && nodeSeqLen(n.List) == 0 {
 			break OpSwitch
 		}
-		typecheckaste(ORETURN, nil, false, getoutargx(Curfn.Type), n.List, func() string { return "return argument" })
+		typecheckaste(ORETURN, nil, false, Curfn.Type.Results(), n.List, func() string { return "return argument" })
 		break OpSwitch
 
 	case ORETJMP:
@@ -2438,7 +2438,7 @@
 	}
 
 	// disallow T.m if m requires *T receiver
-	if Isptr[getthisx(f2.Type).Type.Type.Etype] && !Isptr[t.Etype] && f2.Embedded != 2 && !isifacemethod(f2.Type) {
+	if Isptr[f2.Type.Recv().Type.Type.Etype] && !Isptr[t.Etype] && f2.Embedded != 2 && !isifacemethod(f2.Type) {
 		Yyerror("invalid method expression %v (needs pointer receiver: (*%v).%v)", n, t, Sconv(f2.Sym, obj.FmtShort))
 		return false
 	}
@@ -2521,7 +2521,7 @@
 		}
 		tt := n.Left.Type
 		dowidth(tt)
-		rcvr := getthisx(f2.Type).Type.Type
+		rcvr := f2.Type.Recv().Type.Type
 		if !Eqtype(rcvr, tt) {
 			if rcvr.Etype == Tptr && Eqtype(rcvr.Type, tt) {
 				checklvalue(n.Left, "call pointer method on")
@@ -3445,7 +3445,7 @@
 	}
 	n.Type = t
 	t.Nname = n.Func.Nname
-	rcvr := getthisx(t).Type
+	rcvr := t.Recv().Type
 	if rcvr != nil && n.Func.Shortname != nil {
 		addmethod(n.Func.Shortname.Sym, t, true, n.Func.Nname.Nointerface)
 	}
@@ -3508,7 +3508,7 @@
 	// value of its argument, a specific implementation of I may
 	// care. The _ would suppress the assignment to that argument
 	// while generating a call, so remove it.
-	for t := getinargx(nt.Type).Type; t != nil; t = t.Down {
+	for t, it := IterFields(nt.Type.Params()); t != nil; t = it.Next() {
 		if t.Sym != nil && t.Sym.Name == "_" {
 			t.Sym = nil
 		}
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 56de81f..1db951c 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -328,7 +328,7 @@
 			break
 		}
 
-		ll := ascompatte(n.Op, nil, false, Getoutarg(Curfn.Type), n.List.Slice(), 1, &n.Ninit)
+		ll := ascompatte(n.Op, nil, false, Curfn.Type.ResultsP(), n.List.Slice(), 1, &n.Ninit)
 		setNodeSeq(&n.List, ll)
 
 	case ORETJMP:
@@ -638,7 +638,7 @@
 		}
 		walkexpr(&n.Left, init)
 		walkexprlist(n.List.Slice(), init)
-		ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List.Slice(), 0, init)
+		ll := ascompatte(n.Op, n, n.Isddd, t.ParamsP(), n.List.Slice(), 0, init)
 		setNodeSeq(&n.List, reorder1(ll))
 
 	case OCALLFUNC:
@@ -657,13 +657,13 @@
 			// Update type of OCALLFUNC node.
 			// Output arguments had not changed, but their offsets could.
 			if n.Left.Type.Outtuple == 1 {
-				t := getoutargx(n.Left.Type).Type
+				t := n.Left.Type.Results().Type
 				if t.Etype == TFIELD {
 					t = t.Type
 				}
 				n.Type = t
 			} else {
-				n.Type = getoutargx(n.Left.Type)
+				n.Type = n.Left.Type.Results()
 			}
 		}
 
@@ -685,7 +685,7 @@
 			}
 		}
 
-		ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List.Slice(), 0, init)
+		ll := ascompatte(n.Op, n, n.Isddd, t.ParamsP(), n.List.Slice(), 0, init)
 		setNodeSeq(&n.List, reorder1(ll))
 
 	case OCALLMETH:
@@ -695,8 +695,8 @@
 		}
 		walkexpr(&n.Left, init)
 		walkexprlist(n.List.Slice(), init)
-		ll := ascompatte(n.Op, n, false, getthis(t), []*Node{n.Left.Left}, 0, init)
-		lr := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List.Slice(), 0, init)
+		ll := ascompatte(n.Op, n, false, t.RecvP(), []*Node{n.Left.Left}, 0, init)
+		lr := ascompatte(n.Op, n, n.Isddd, t.ParamsP(), n.List.Slice(), 0, init)
 		ll = append(ll, lr...)
 		n.Left.Left = nil
 		ullmancalc(n.Left)
@@ -870,7 +870,7 @@
 		a := nodeSeqFirst(n.List)
 
 		fn := mapfn(p, t)
-		r = mkcall1(fn, getoutargx(fn.Type), init, typename(t), r.Left, key)
+		r = mkcall1(fn, fn.Type.Results(), init, typename(t), r.Left, key)
 
 		// mapaccess2* returns a typed bool, but due to spec changes,
 		// the boolean result of i.(T) is now untyped so we make it the
@@ -2031,7 +2031,7 @@
 			continue
 		}
 
-		t = getinargx(on.Type)
+		t = on.Type.Params()
 		if t != nil {
 			t = t.Type
 		}
@@ -2650,12 +2650,12 @@
 func heapmoves() {
 	lno := lineno
 	lineno = Curfn.Lineno
-	nn := paramstoheap(getthis(Curfn.Type), 0)
-	nn = append(nn, paramstoheap(getinarg(Curfn.Type), 0)...)
-	nn = append(nn, paramstoheap(Getoutarg(Curfn.Type), 1)...)
+	nn := paramstoheap(Curfn.Type.RecvP(), 0)
+	nn = append(nn, paramstoheap(Curfn.Type.ParamsP(), 0)...)
+	nn = append(nn, paramstoheap(Curfn.Type.ResultsP(), 1)...)
 	Curfn.Func.Enter.Append(nn...)
 	lineno = Curfn.Func.Endlineno
-	Curfn.Func.Exit.Append(returnsfromheap(Getoutarg(Curfn.Type))...)
+	Curfn.Func.Exit.Append(returnsfromheap(Curfn.Type.ResultsP())...)
 	lineno = lno
 }