From 7758a9405f45970cb545505b9adcaccc6b23e7e7 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 8 Mar 2016 15:02:40 -0800 Subject: [PATCH] cmd/compile: simplify Iter Passes toolstash -cmp. Change-Id: I325b02dcc8412ded0dc304d43377c0bdf59c66a8 Reviewed-on: https://go-review.googlesource.com/20405 Reviewed-by: David Crawshaw Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/align.go | 25 ++--- src/cmd/compile/internal/gc/cgen.go | 12 +-- src/cmd/compile/internal/gc/gsubr.go | 3 +- src/cmd/compile/internal/gc/order.go | 3 +- src/cmd/compile/internal/gc/pgen.go | 3 +- src/cmd/compile/internal/gc/ssa.go | 3 +- src/cmd/compile/internal/gc/subr.go | 7 +- src/cmd/compile/internal/gc/type.go | 115 ++++++----------------- src/cmd/compile/internal/gc/typecheck.go | 5 +- src/cmd/compile/internal/gc/walk.go | 31 +++--- 10 files changed, 63 insertions(+), 144 deletions(-) diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index e8d84469c23..ed5b55489bf 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -295,9 +295,9 @@ func dowidth(t *Type) { 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 @@ func typeinit() { // 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 7286d3932cc..ee4179d957e 100644 --- a/src/cmd/compile/internal/gc/cgen.go +++ b/src/cmd/compile/internal/gc/cgen.go @@ -1677,8 +1677,7 @@ func Igen(n *Node, a *Node, res *Node) { 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 @@ func stkof(n *Node) int64 { 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 @@ func cgen_callret(n *Node, res *Node) { 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 @@ func cgen_aret(n *Node, res *Node) { 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 a194821e3a0..d7f6232b963 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -548,8 +548,7 @@ func nodarg(t *Type, fp int) *Node { 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 9484ab3af74..8ffc1c7cf73 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -338,8 +338,7 @@ func copyret(n *Node, order *Order) Nodes { 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 26c276555bc..c4773f69290 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -377,8 +377,7 @@ func compile(fn *Node) { 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 b1745a9fc03..9dc3ce8d455 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2407,8 +2407,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // 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 5eba2523bf1..32463139980 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1892,14 +1892,13 @@ func expandmeth(t *Type) { // 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 @@ func liststmt(l []*Node) *Node { // 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 095f8148255..71fc8b16ff1 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -164,101 +164,48 @@ type Type struct { 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 2d9627eb53c..44aeef683f9 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3371,8 +3371,7 @@ func typecheckas2(n *Node) { 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 @@ func typecheckas2(n *Node) { 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 81f2e7e6065..56de81f9a16 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1706,12 +1706,11 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node { 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 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node { } l = it.N() if isblank(l) { - r = structnext(&saver) + r = saver.Next() continue } @@ -1748,7 +1747,7 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node { } nn = append(nn, a) - r = structnext(&saver) + r = saver.Next() } if !it.Done() || r != nil { @@ -1797,12 +1796,10 @@ func mkdotargslice(lr0, nn []*Node, l *Type, fp int, init *Nodes, ddd *Node) []* // 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 @@ func dumpnodetypes(l []*Node, what string) string { // 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 @@ func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr []*Node, fp int, in // 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 @@ func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr []*Node, fp int, in 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 @@ loop: 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 @@ func walkprint(nn *Node, init *Nodes) *Node { continue } - t = *getinarg(on.Type) + t = getinargx(on.Type) if t != nil { t = t.Type } @@ -2590,12 +2585,11 @@ func vmatch1(l *Node, r *Node) bool { // 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 @@ func paramstoheap(argin **Type, out int) []*Node { // 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