]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add Key, FieldSlice, and SetFields helpers
authorMatthew Dempsky <mdempsky@google.com>
Thu, 10 Mar 2016 13:22:14 +0000 (05:22 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 10 Mar 2016 23:34:22 +0000 (23:34 +0000)
Allows safely eliminating more direct uses of Type's Type and Down
fields.

Passes toolstash -cmp.

Change-Id: I5c17fe541a0473c3cd2978d8314c4ab759079a61
Reviewed-on: https://go-review.googlesource.com/20541
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
12 files changed:
src/cmd/compile/internal/gc/align.go
src/cmd/compile/internal/gc/bexport.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/range.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/sinit.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/type.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/unsafe.go
src/cmd/compile/internal/gc/walk.go

index 2dc3f41212e9540330f686b413319f7854800a99..cabb0a9bae481e5d056e01391c534787fb26c786 100644 (file)
@@ -223,7 +223,7 @@ func dowidth(t *Type) {
                w = int64(Widthptr)
 
                checkwidth(t.Type)
-               checkwidth(t.Down)
+               checkwidth(t.Key())
 
        case TFORW: // should have been filled in
                if !t.Broke {
index 6bb14dea2faf7cf96510d7922682fd4e81eeeab5..67b0f97c0fb4145667976273f970fe10603992b2 100644 (file)
@@ -534,8 +534,8 @@ func (p *exporter) typ(t *Type) {
 
        case TMAP:
                p.tag(mapTag)
-               p.typ(t.Down) // key
-               p.typ(t.Type) // val
+               p.typ(t.Key()) // key
+               p.typ(t.Type)  // val
 
        case TCHAN:
                p.tag(chanTag)
index 6f029146437d9272b8d5fdbc77e0ec62ef06badb..8c9906cc162753e413411a8ff965b43f4b2728f3 100644 (file)
@@ -827,12 +827,11 @@ func tostruct0(t *Type, l []*Node) {
                Fatalf("struct expected")
        }
 
-       tp := &t.Type
+       var fields []*Type
        for _, n := range l {
-               f := structfield(n)
-               *tp = f
-               tp = &f.Down
+               fields = append(fields, structfield(n))
        }
+       t.SetFields(fields)
 
        for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
                if f.Broke {
@@ -849,14 +848,12 @@ func tostruct0(t *Type, l []*Node) {
 }
 
 func tofunargs(l []*Node) *Type {
-       var f *Type
-
        t := typ(TSTRUCT)
        t.Funarg = true
 
-       tp := &t.Type
+       var fields []*Type
        for _, n := range l {
-               f = structfield(n)
+               f := structfield(n)
                f.Funarg = true
 
                // esc.go needs to find f given a PPARAM to add the tag.
@@ -864,9 +861,9 @@ func tofunargs(l []*Node) *Type {
                        n.Left.Name.Param.Field = f
                }
 
-               *tp = f
-               tp = &f.Down
+               fields = append(fields, f)
        }
+       t.SetFields(fields)
 
        for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
                if f.Broke {
@@ -955,7 +952,7 @@ func tointerface0(t *Type, l []*Node) *Type {
                Fatalf("interface expected")
        }
 
-       tp := &t.Type
+       var fields []*Type
        for _, n := range l {
                f := interfacefield(n)
 
@@ -969,14 +966,13 @@ func tointerface0(t *Type, l []*Node) *Type {
                                if f.Sym != nil {
                                        f.Nname = newname(f.Sym)
                                }
-                               *tp = f
-                               tp = &f.Down
+                               fields = append(fields, f)
                        }
                } else {
-                       *tp = f
-                       tp = &f.Down
+                       fields = append(fields, f)
                }
        }
+       t.SetFields(fields)
 
        for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
                if f.Broke {
index 6d7a50a98b4883878798a64a18966c45a5de7c95..4597cebffd13cc9d611fa65cfe06d2ac0284df70 100644 (file)
@@ -580,7 +580,7 @@ func typefmt(t *Type, flag int) string {
                return fmt.Sprintf("chan %v", t.Type)
 
        case TMAP:
-               return fmt.Sprintf("map[%v]%v", t.Down, t.Type)
+               return fmt.Sprintf("map[%v]%v", t.Key(), t.Type)
 
        case TINTER:
                var buf bytes.Buffer
@@ -645,15 +645,15 @@ func typefmt(t *Type, flag int) string {
                        // Format the bucket struct for map[x]y as map.bucket[x]y.
                        // This avoids a recursive print that generates very long names.
                        if t.Map.Bucket == t {
-                               return fmt.Sprintf("map.bucket[%v]%v", t.Map.Down, t.Map.Type)
+                               return fmt.Sprintf("map.bucket[%v]%v", t.Map.Key(), t.Map.Type)
                        }
 
                        if t.Map.Hmap == t {
-                               return fmt.Sprintf("map.hdr[%v]%v", t.Map.Down, t.Map.Type)
+                               return fmt.Sprintf("map.hdr[%v]%v", t.Map.Key(), t.Map.Type)
                        }
 
                        if t.Map.Hiter == t {
-                               return fmt.Sprintf("map.iter[%v]%v", t.Map.Down, t.Map.Type)
+                               return fmt.Sprintf("map.iter[%v]%v", t.Map.Key(), t.Map.Type)
                        }
 
                        Yyerror("unknown internal map type")
index d4df16b52bd65ac805cb8b9c6e7fef628f2da49e..1459b7a47701d55c676fe738d94497a874a2d00e 100644 (file)
@@ -56,7 +56,7 @@ func typecheckrange(n *Node) {
                t2 = t.Type
 
        case TMAP:
-               t1 = t.Down
+               t1 = t.Key()
                t2 = t.Type
 
        case TCHAN:
@@ -228,12 +228,12 @@ func walkrange(n *Node) {
                hit := prealloc[n]
                hit.Type = th
                n.Left = nil
-               keyname := newname(th.Type.Sym)      // depends on layout of iterator struct.  See reflect.go:hiter
-               valname := newname(th.Type.Down.Sym) // ditto
+               keyname := newname(th.Field(0).Sym) // depends on layout of iterator struct.  See reflect.go:hiter
+               valname := newname(th.Field(1).Sym) // ditto
 
                fn := syslook("mapiterinit")
 
-               substArgTypes(&fn, t.Down, t.Type, th)
+               substArgTypes(&fn, t.Key(), t.Type, th)
                init = append(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
                n.Left = Nod(ONE, Nod(ODOT, hit, keyname), nodnil())
 
index 306f7c7d36d509f5d26a29998dd0ad9629ac0e9d..b9cc215c8e1f43058a3bf9c2d66c527b48571502 100644 (file)
@@ -75,7 +75,7 @@ func mapbucket(t *Type) *Type {
        }
 
        bucket := typ(TSTRUCT)
-       keytype := t.Down
+       keytype := t.Key()
        valtype := t.Type
        dowidth(keytype)
        dowidth(valtype)
@@ -119,7 +119,7 @@ func mapbucket(t *Type) *Type {
        // so if the struct needs 64-bit padding (because a key or value does)
        // then it would end with an extra 32-bit padding field.
        // Preempt that by emitting the padding here.
-       if int(t.Type.Align) > Widthptr || int(t.Down.Align) > Widthptr {
+       if int(t.Type.Align) > Widthptr || int(t.Key().Align) > Widthptr {
                field = append(field, makefield("pad", Types[TUINTPTR]))
        }
 
@@ -130,7 +130,7 @@ func mapbucket(t *Type) *Type {
        // the type of the overflow field to uintptr in this case.
        // See comment on hmap.overflow in ../../../../runtime/hashmap.go.
        otyp := Ptrto(bucket)
-       if !haspointers(t.Type) && !haspointers(t.Down) && t.Type.Width <= MAXKEYSIZE && t.Down.Width <= MAXVALSIZE {
+       if !haspointers(t.Type) && !haspointers(t.Key()) && t.Type.Width <= MAXVALSIZE && t.Key().Width <= MAXKEYSIZE {
                otyp = Types[TUINTPTR]
        }
        ovf := makefield("overflow", otyp)
@@ -139,11 +139,7 @@ func mapbucket(t *Type) *Type {
        // link up fields
        bucket.Noalg = true
        bucket.Local = t.Local
-       bucket.Type = field[0]
-       for n := int32(0); n < int32(len(field)-1); n++ {
-               field[n].Down = field[n+1]
-       }
-       field[len(field)-1].Down = nil
+       bucket.SetFields(field[:])
        dowidth(bucket)
 
        // Double-check that overflow field is final memory in struct,
@@ -179,11 +175,7 @@ func hmap(t *Type) *Type {
        h := typ(TSTRUCT)
        h.Noalg = true
        h.Local = t.Local
-       h.Type = field[0]
-       for n := int32(0); n < int32(len(field)-1); n++ {
-               field[n].Down = field[n+1]
-       }
-       field[len(field)-1].Down = nil
+       h.SetFields(field[:])
        dowidth(h)
        t.Hmap = h
        h.Map = t
@@ -212,8 +204,7 @@ func hiter(t *Type) *Type {
        // }
        // must match ../../../../runtime/hashmap.go:hiter.
        var field [12]*Type
-       field[0] = makefield("key", Ptrto(t.Down))
-
+       field[0] = makefield("key", Ptrto(t.Key()))
        field[1] = makefield("val", Ptrto(t.Type))
        field[2] = makefield("t", Ptrto(Types[TUINT8]))
        field[3] = makefield("h", Ptrto(hmap(t)))
@@ -228,13 +219,8 @@ func hiter(t *Type) *Type {
 
        // build iterator struct holding the above fields
        i := typ(TSTRUCT)
-
        i.Noalg = true
-       i.Type = field[0]
-       for n := int32(0); n < int32(len(field)-1); n++ {
-               field[n].Down = field[n+1]
-       }
-       field[len(field)-1].Down = nil
+       i.SetFields(field[:])
        dowidth(i)
        if i.Width != int64(12*Widthptr) {
                Yyerror("hash_iter size not correct %d %d", i.Width, 12*Widthptr)
@@ -1124,8 +1110,7 @@ ok:
 
        // ../../../../runtime/type.go:/mapType
        case TMAP:
-               s1 := dtypesym(t.Down)
-
+               s1 := dtypesym(t.Key())
                s2 := dtypesym(t.Type)
                s3 := dtypesym(mapbucket(t))
                s4 := dtypesym(hmap(t))
@@ -1134,11 +1119,11 @@ ok:
                ot = dsymptr(s, ot, s2, 0)
                ot = dsymptr(s, ot, s3, 0)
                ot = dsymptr(s, ot, s4, 0)
-               if t.Down.Width > MAXKEYSIZE {
+               if t.Key().Width > MAXKEYSIZE {
                        ot = duint8(s, ot, uint8(Widthptr))
                        ot = duint8(s, ot, 1) // indirect
                } else {
-                       ot = duint8(s, ot, uint8(t.Down.Width))
+                       ot = duint8(s, ot, uint8(t.Key().Width))
                        ot = duint8(s, ot, 0) // not indirect
                }
 
@@ -1151,8 +1136,8 @@ ok:
                }
 
                ot = duint16(s, ot, uint16(mapbucket(t).Width))
-               ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Down))))
-               ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Down))))
+               ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Key()))))
+               ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Key()))))
                ot = dextratype(s, ot, t, 0)
 
        case TPTR32, TPTR64:
index 6edfe53dae82292b0f889473167562b3cbd16652..3b0d2693955163ef424f566108bd3de554532352 100644 (file)
@@ -979,7 +979,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
                // build list of var[c] = expr.
                // use temporary so that mapassign1 can have addressable key, val.
                if key == nil {
-                       key = temp(var_.Type.Down)
+                       key = temp(var_.Type.Key())
                        val = temp(var_.Type.Type)
                }
 
index 6c6816570d617927c0c8aa9f23544b130cb829c5..96fca9493c7a18362594e9aaaf7f7a84ae967ac1 100644 (file)
@@ -417,23 +417,9 @@ func (x methcmp) Less(i, j int) bool {
 }
 
 func sortinter(t *Type) *Type {
-       if t.Type == nil || t.Type.Down == nil {
-               return t
-       }
-
-       var a []*Type
-       for f, it := IterFields(t); f != nil; f = it.Next() {
-               a = append(a, f)
-       }
-       sort.Sort(methcmp(a))
-
-       n := len(a) // n > 0 due to initial conditions.
-       for i := 0; i < n-1; i++ {
-               a[i].Down = a[i+1]
-       }
-       a[n-1].Down = nil
-
-       t.Type = a[0]
+       s := t.FieldSlice()
+       sort.Sort(methcmp(s))
+       t.SetFields(s)
        return t
 }
 
@@ -740,12 +726,9 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
 
        switch t1.Etype {
        case TINTER, TSTRUCT:
-               t1 = t1.Type
-               t2 = t2.Type
-               for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
-                       if t1.Etype != TFIELD || t2.Etype != TFIELD {
-                               Fatalf("struct/interface missing field: %v %v", t1, t2)
-                       }
+               t1, i1 := IterFields(t1)
+               t2, i2 := IterFields(t2)
+               for ; t1 != nil && t2 != nil; t1, t2 = i1.Next(), i2.Next() {
                        if t1.Sym != t2.Sym || t1.Embedded != t2.Embedded || !eqtype1(t1.Type, t2.Type, assumedEqual) || !eqnote(t1.Note, t2.Note) {
                                return false
                        }
@@ -782,9 +765,14 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
                if t1.Chan != t2.Chan {
                        return false
                }
+
+       case TMAP:
+               if !eqtype1(t1.Key(), t2.Key(), assumedEqual) {
+                       return false
+               }
        }
 
-       return eqtype1(t1.Down, t2.Down, assumedEqual) && eqtype1(t1.Type, t2.Type, assumedEqual)
+       return eqtype1(t1.Type, t2.Type, assumedEqual)
 }
 
 // Are t1 and t2 equal struct types when field names are ignored?
@@ -795,8 +783,8 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
                return false
        }
 
-       t1 = t1.Type
-       t2 = t2.Type
+       t1, i1 := IterFields(t1)
+       t2, i2 := IterFields(t2)
        for {
                if !Eqtype(t1, t2) {
                        return false
@@ -804,8 +792,8 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
                if t1 == nil {
                        return true
                }
-               t1 = t1.Down
-               t2 = t2.Down
+               t1 = i1.Next()
+               t2 = i2.Next()
        }
 }
 
@@ -2635,13 +2623,13 @@ func isdirectiface(t *Type) bool {
                TUNSAFEPTR:
                return true
 
-               // Array of 1 direct iface type can be direct.
        case TARRAY:
+               // Array of 1 direct iface type can be direct.
                return t.Bound == 1 && isdirectiface(t.Type)
 
-               // Struct with 1 field of direct iface type can be direct.
        case TSTRUCT:
-               return t.Type != nil && t.Type.Down == nil && isdirectiface(t.Type.Type)
+               // Struct with 1 field of direct iface type can be direct.
+               return countfield(t) == 1 && isdirectiface(t.Field(0).Type)
        }
 
        return false
index ec06407ecf937515fb4c8eaeee3d6ce583446bea..e5e12f0bb8f3a8ef73cf39039fdb19454128c16e 100644 (file)
@@ -274,6 +274,12 @@ var recvsParamsResults = [3]func(*Type) *Type{
        (*Type).Recvs, (*Type).Params, (*Type).Results,
 }
 
+// Key returns the key type of map type t.
+func (t *Type) Key() *Type {
+       t.wantEtype(TMAP)
+       return t.Down
+}
+
 // Field returns the i'th field/method of struct/interface type t.
 func (t *Type) Field(i int) *Type {
        // TODO: store fields in a slice so we can
@@ -294,6 +300,29 @@ func (t *Type) Field(i int) *Type {
        panic("not enough fields")
 }
 
+// FieldSlice returns a slice of containing all fields/methods of
+// struct/interface type t.
+func (t *Type) FieldSlice() []*Type {
+       var s []*Type
+       for f, it := IterFields(t); f != nil; f = it.Next() {
+               s = append(s, f)
+       }
+       return s
+}
+
+// SetFields sets struct/interface type t's fields/methods to fields.
+func (t *Type) SetFields(fields []*Type) {
+       if t.Etype != TSTRUCT && t.Etype != TINTER {
+               Fatalf("SetFields: type %v does not have fields", t)
+       }
+       var next *Type
+       for i := len(fields) - 1; i >= 0; i-- {
+               fields[i].Down = next
+               next = fields[i]
+       }
+       t.Type = next
+}
+
 func (t *Type) Size() int64 {
        dowidth(t)
        return t.Width
index fe2560e9f84f8f66d41ee3090a09d3bf33d751d9..7840878da1a8eaf76f5a02c24d946887f68ee968 100644 (file)
@@ -1021,9 +1021,9 @@ OpSwitch:
 
                case TMAP:
                        n.Etype = 0
-                       defaultlit(&n.Right, t.Down)
+                       defaultlit(&n.Right, t.Key())
                        if n.Right.Type != nil {
-                               n.Right = assignconv(n.Right, t.Down, "map index")
+                               n.Right = assignconv(n.Right, t.Key(), "map index")
                        }
                        n.Type = t.Type
                        n.Op = OINDEXMAP
@@ -1460,9 +1460,9 @@ OpSwitch:
                                return
                        }
 
-                       t = n.List.First().Type.Type
-                       l = t.Nname
-                       r = t.Down.Nname
+                       t = n.List.First().Type
+                       l = t.Field(0).Nname
+                       r = t.Field(1).Nname
                } else {
                        if !twoarg(n) {
                                n.Type = nil
@@ -1575,7 +1575,7 @@ OpSwitch:
                        return
                }
 
-               args.SetIndex(1, assignconv(r, l.Type.Down, "delete"))
+               args.SetIndex(1, assignconv(r, l.Type.Key(), "delete"))
                break OpSwitch
 
        case OAPPEND:
@@ -3028,10 +3028,10 @@ func typecheckcomplit(np **Node) {
                        }
 
                        r = l.Left
-                       pushtype(r, t.Down)
+                       pushtype(r, t.Key())
                        typecheck(&r, Erv)
-                       defaultlit(&r, t.Down)
-                       l.Left = assignconv(r, t.Down, "map key")
+                       defaultlit(&r, t.Key())
+                       l.Left = assignconv(r, t.Key(), "map key")
                        if l.Left.Op != OCONV {
                                keydup(l.Left, hash)
                        }
index 99e0ac82d7eefb080e6ad08bde2611b78329f97a..7cac8516c37ab03177d3e11948d5fad66e979ebf 100644 (file)
@@ -104,19 +104,21 @@ func unsafenmagic(nn *Node) *Node {
                        goto bad
                }
 
+               var f [2]*Type
+               f[0] = typ(TFIELD)
+               f[0].Type = Types[TUINT8]
+               f[1] = typ(TFIELD)
+               f[1].Type = tr
+
                // make struct { byte; T; }
                t := typ(TSTRUCT)
-
-               t.Type = typ(TFIELD)
-               t.Type.Type = Types[TUINT8]
-               t.Type.Down = typ(TFIELD)
-               t.Type.Down.Type = tr
+               t.SetFields(f[:])
 
                // compute struct widths
                dowidth(t)
 
                // the offset of T is its required alignment
-               v = t.Type.Down.Width
+               v = t.Field(1).Width
 
                goto yes
        }
index 3c397dfc1b792687525870d63abb6c10eb484cdf..be0d5ff25828653139d0238d888523300926c82f 100644 (file)
@@ -840,7 +840,7 @@ opswitch:
                t := r.Left.Type
                p := ""
                if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
-                       switch algtype(t.Down) {
+                       switch algtype(t.Key()) {
                        case AMEM32:
                                p = "mapaccess2_fast32"
                        case AMEM64:
@@ -876,7 +876,7 @@ opswitch:
                // the boolean result of i.(T) is now untyped so we make it the
                // same type as the variable on the lhs.
                if !isblank(n.List.Second()) {
-                       r.Type.Type.Down.Type = n.List.Second().Type
+                       r.Type.Field(1).Type = n.List.Second().Type
                }
                n.Rlist.Set1(r)
                n.Op = OAS2FUNC
@@ -1247,7 +1247,7 @@ opswitch:
                t := n.Left.Type
                p := ""
                if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
-                       switch algtype(t.Down) {
+                       switch algtype(t.Key()) {
                        case AMEM32:
                                p = "mapaccess1_fast32"
                        case AMEM64:
@@ -1439,7 +1439,7 @@ opswitch:
                }
 
                fn := syslook("makemap")
-               substArgTypes(&fn, hmap(t), mapbucket(t), t.Down, t.Type)
+               substArgTypes(&fn, hmap(t), mapbucket(t), t.Key(), t.Type)
                n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
 
        case OMAKESLICE:
@@ -2690,7 +2690,7 @@ func mapfn(name string, t *Type) *Node {
                Fatalf("mapfn %v", t)
        }
        fn := syslook(name)
-       substArgTypes(&fn, t.Down, t.Type, t.Down, t.Type)
+       substArgTypes(&fn, t.Key(), t.Type, t.Key(), t.Type)
        return fn
 }
 
@@ -2699,7 +2699,7 @@ func mapfndel(name string, t *Type) *Node {
                Fatalf("mapfn %v", t)
        }
        fn := syslook(name)
-       substArgTypes(&fn, t.Down, t.Type, t.Down)
+       substArgTypes(&fn, t.Key(), t.Type, t.Key())
        return fn
 }