]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: add Interface, Signature, and Struct constructors
authorMatthew Dempsky <mdempsky@google.com>
Tue, 1 Dec 2020 21:07:35 +0000 (13:07 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 2 Dec 2020 06:42:17 +0000 (06:42 +0000)
This CL adds the remaining constructors needed to abstract away
construction of Types, and updates the compiler to use them
throughout. There's now just a couple uses within test cases to
remove.

While at it, I also replace the Func.Outnamed field with a simple
helper function, which reduces the size of function types somewhat.

Passes toolstash/buildall.

Change-Id: If1aa1095c98ae34b00380d0b3531bd63c10ce885
Reviewed-on: https://go-review.googlesource.com/c/go/+/274713
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/pgen_test.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/universe.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/types/sizeof_test.go
src/cmd/compile/internal/types/type.go

index dd59d829fedf22d3fd29a7bd30d0e6eb68fde072..e0c87d4517c48eab4089c0acf2e08f048818496e 100644 (file)
@@ -369,7 +369,7 @@ func funchdr(fn *ir.Func) {
 
        types.Markdcl()
 
-       if fn.Nname != nil && fn.Nname.Ntype != nil {
+       if fn.Nname.Ntype != nil {
                funcargs(fn.Nname.Ntype.(*ir.FuncType))
        } else {
                funcargs2(fn.Type())
@@ -510,27 +510,6 @@ func checkembeddedtype(t *types.Type) {
        }
 }
 
-func structfield(n *ir.Field) *types.Field {
-       lno := base.Pos
-       base.Pos = n.Pos
-
-       if n.Ntype != nil {
-               n.Ntype = typecheckNtype(n.Ntype)
-               n.Type = n.Ntype.Type()
-               n.Ntype = nil
-       }
-
-       f := types.NewField(n.Pos, n.Sym, n.Type)
-       if n.Embedded {
-               checkembeddedtype(n.Type)
-               f.Embedded = 1
-       }
-       f.Note = n.Note
-
-       base.Pos = lno
-       return f
-}
-
 // checkdupfields emits errors for duplicately named fields or methods in
 // a list of struct or interface types.
 func checkdupfields(what string, fss ...[]*types.Field) {
@@ -552,95 +531,49 @@ func checkdupfields(what string, fss ...[]*types.Field) {
 // convert a parsed id/type list into
 // a type for struct/interface/arglist
 func tostruct(l []*ir.Field) *types.Type {
-       t := types.New(types.TSTRUCT)
+       lno := base.Pos
 
        fields := make([]*types.Field, len(l))
        for i, n := range l {
-               f := structfield(n)
-               if f.Broke() {
-                       t.SetBroke(true)
-               }
-               fields[i] = f
-       }
-       t.SetFields(fields)
-
-       checkdupfields("field", t.FieldSlice())
-
-       if !t.Broke() {
-               checkwidth(t)
-       }
+               base.Pos = n.Pos
 
-       return t
-}
-
-func tofunargs(l []*ir.Field, funarg types.Funarg) *types.Type {
-       t := types.New(types.TSTRUCT)
-       t.StructType().Funarg = funarg
-
-       fields := make([]*types.Field, len(l))
-       for i, n := range l {
-               f := structfield(n)
-               f.SetIsDDD(n.IsDDD)
-               if n.Decl != nil {
-                       n.Decl.SetType(f.Type)
-                       f.Nname = n.Decl
+               if n.Ntype != nil {
+                       n.Type = typecheckNtype(n.Ntype).Type()
+                       n.Ntype = nil
                }
-               if f.Broke() {
-                       t.SetBroke(true)
+               f := types.NewField(n.Pos, n.Sym, n.Type)
+               if n.Embedded {
+                       checkembeddedtype(n.Type)
+                       f.Embedded = 1
                }
+               f.Note = n.Note
                fields[i] = f
        }
-       t.SetFields(fields)
-       return t
-}
+       checkdupfields("field", fields)
 
-func tofunargsfield(fields []*types.Field, funarg types.Funarg) *types.Type {
-       t := types.New(types.TSTRUCT)
-       t.StructType().Funarg = funarg
-       t.SetFields(fields)
-       return t
+       base.Pos = lno
+       return types.NewStruct(fields)
 }
 
-func interfacefield(n *ir.Field) *types.Field {
-       lno := base.Pos
-       base.Pos = n.Pos
-
-       if n.Note != "" {
-               base.Errorf("interface method cannot have annotation")
+func tointerface(nmethods []*ir.Field) *types.Type {
+       if len(nmethods) == 0 {
+               return types.Types[types.TINTER]
        }
 
-       // MethodSpec = MethodName Signature | InterfaceTypeName .
-       //
-       // If Sym != nil, then Sym is MethodName and Left is Signature.
-       // Otherwise, Left is InterfaceTypeName.
+       lno := base.Pos
 
-       if n.Ntype != nil {
-               n.Ntype = typecheckNtype(n.Ntype)
-               n.Type = n.Ntype.Type()
-               n.Ntype = nil
+       methods := make([]*types.Field, len(nmethods))
+       for i, n := range nmethods {
+               base.Pos = n.Pos
+               if n.Ntype != nil {
+                       n.Type = typecheckNtype(n.Ntype).Type()
+                       n.Ntype = nil
+               }
+               methods[i] = types.NewField(n.Pos, n.Sym, n.Type)
        }
 
-       f := types.NewField(n.Pos, n.Sym, n.Type)
-
        base.Pos = lno
-       return f
-}
-
-func tointerface(l []*ir.Field) *types.Type {
-       if len(l) == 0 {
-               return types.Types[types.TINTER]
-       }
-       t := types.New(types.TINTER)
-       var fields []*types.Field
-       for _, n := range l {
-               f := interfacefield(n)
-               if f.Broke() {
-                       t.SetBroke(true)
-               }
-               fields = append(fields, f)
-       }
-       t.SetInterface(fields)
-       return t
+       return types.NewInterface(methods)
 }
 
 func fakeRecv() *ir.Field {
@@ -659,42 +592,47 @@ func isifacemethod(f *types.Type) bool {
 }
 
 // turn a parsed function declaration into a type
-func functype(this *ir.Field, in, out []*ir.Field) *types.Type {
-       t := types.New(types.TFUNC)
-
-       var rcvr []*ir.Field
-       if this != nil {
-               rcvr = []*ir.Field{this}
-       }
-       t.FuncType().Receiver = tofunargs(rcvr, types.FunargRcvr)
-       t.FuncType().Params = tofunargs(in, types.FunargParams)
-       t.FuncType().Results = tofunargs(out, types.FunargResults)
+func functype(nrecv *ir.Field, nparams, nresults []*ir.Field) *types.Type {
+       funarg := func(n *ir.Field) *types.Field {
+               lno := base.Pos
+               base.Pos = n.Pos
+
+               if n.Ntype != nil {
+                       n.Type = typecheckNtype(n.Ntype).Type()
+                       n.Ntype = nil
+               }
 
-       checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
+               f := types.NewField(n.Pos, n.Sym, n.Type)
+               f.SetIsDDD(n.IsDDD)
+               if n.Decl != nil {
+                       n.Decl.SetType(f.Type)
+                       f.Nname = n.Decl
+               }
 
-       if t.Recvs().Broke() || t.Results().Broke() || t.Params().Broke() {
-               t.SetBroke(true)
+               base.Pos = lno
+               return f
+       }
+       funargs := func(nn []*ir.Field) []*types.Field {
+               res := make([]*types.Field, len(nn))
+               for i, n := range nn {
+                       res[i] = funarg(n)
+               }
+               return res
        }
 
-       t.FuncType().Outnamed = t.NumResults() > 0 && ir.OrigSym(t.Results().Field(0).Sym) != nil
+       var recv *types.Field
+       if nrecv != nil {
+               recv = funarg(nrecv)
+       }
 
+       t := types.NewSignature(recv, funargs(nparams), funargs(nresults))
+       checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
        return t
 }
 
-func functypefield(this *types.Field, in, out []*types.Field) *types.Type {
-       t := types.New(types.TFUNC)
-
-       var rcvr []*types.Field
-       if this != nil {
-               rcvr = []*types.Field{this}
-       }
-       t.FuncType().Receiver = tofunargsfield(rcvr, types.FunargRcvr)
-       t.FuncType().Params = tofunargsfield(in, types.FunargParams)
-       t.FuncType().Results = tofunargsfield(out, types.FunargResults)
-
-       t.FuncType().Outnamed = t.NumResults() > 0 && ir.OrigSym(t.Results().Field(0).Sym) != nil
-
-       return t
+func hasNamedResults(fn *ir.Func) bool {
+       typ := fn.Type()
+       return typ.NumResults() > 0 && ir.OrigSym(typ.Results().Field(0).Sym) != nil
 }
 
 // methodSym returns the method symbol representing a method name
index 15f1b646f794ce97cff3f0910a6a49fb5c2da404..1bb98415641cb3a8207cf69749d9e08553e6bff4 100644 (file)
@@ -545,9 +545,8 @@ func (r *importReader) typ1() *types.Type {
                        fs[i] = f
                }
 
-               t := types.New(types.TSTRUCT)
+               t := types.NewStruct(fs)
                t.SetPkg(r.currPkg)
-               t.SetFields(fs)
                return t
 
        case interfaceType:
@@ -570,9 +569,8 @@ func (r *importReader) typ1() *types.Type {
                        methods[i] = types.NewField(pos, sym, typ)
                }
 
-               t := types.New(types.TINTER)
+               t := types.NewInterface(append(embeddeds, methods...))
                t.SetPkg(r.currPkg)
-               t.SetInterface(append(embeddeds, methods...))
 
                // Ensure we expand the interface in the frontend (#25055).
                checkwidth(t)
@@ -590,7 +588,7 @@ func (r *importReader) signature(recv *types.Field) *types.Type {
        if n := len(params); n > 0 {
                params[n-1].SetIsDDD(r.bool())
        }
-       t := functypefield(recv, params, results)
+       t := types.NewSignature(recv, params, results)
        t.SetPkg(r.currPkg)
        return t
 }
index 35ce087af62ce40bc5d293d92fc3deaad3540ea3..710bc325349d14e02eeb027555d3f3a0663035ae 100644 (file)
@@ -7,23 +7,22 @@ package gc
 import (
        "cmd/compile/internal/ir"
        "cmd/compile/internal/types"
+       "cmd/internal/src"
        "reflect"
        "sort"
        "testing"
 )
 
 func typeWithoutPointers() *types.Type {
-       t := types.New(types.TSTRUCT)
-       f := &types.Field{Type: types.New(types.TINT)}
-       t.SetFields([]*types.Field{f})
-       return t
+       return types.NewStruct([]*types.Field{
+               types.NewField(src.NoXPos, nil, types.New(types.TINT)),
+       })
 }
 
 func typeWithPointers() *types.Type {
-       t := types.New(types.TSTRUCT)
-       f := &types.Field{Type: types.NewPtr(types.New(types.TINT))}
-       t.SetFields([]*types.Field{f})
-       return t
+       return types.NewStruct([]*types.Field{
+               types.NewField(src.NoXPos, nil, types.NewPtr(types.New(types.TINT))),
+       })
 }
 
 func markUsed(n *ir.Name) *ir.Name {
index 0b860b5f7a404d9e391eebf5f45501d977a4bc98..b249310df0078b5787439f5809c6453ded9c147e 100644 (file)
@@ -126,9 +126,8 @@ func bmap(t *types.Type) *types.Type {
        field = append(field, overflow)
 
        // link up fields
-       bucket := types.New(types.TSTRUCT)
+       bucket := types.NewStruct(field[:])
        bucket.SetNoalg(true)
-       bucket.SetFields(field[:])
        dowidth(bucket)
 
        // Check invariants that map code depends on.
@@ -221,9 +220,8 @@ func hmap(t *types.Type) *types.Type {
                makefield("extra", types.Types[types.TUNSAFEPTR]),
        }
 
-       hmap := types.New(types.TSTRUCT)
+       hmap := types.NewStruct(fields)
        hmap.SetNoalg(true)
-       hmap.SetFields(fields)
        dowidth(hmap)
 
        // The size of hmap should be 48 bytes on 64 bit
@@ -285,9 +283,8 @@ func hiter(t *types.Type) *types.Type {
        }
 
        // build iterator struct holding the above fields
-       hiter := types.New(types.TSTRUCT)
+       hiter := types.NewStruct(fields)
        hiter.SetNoalg(true)
-       hiter.SetFields(fields)
        dowidth(hiter)
        if hiter.Width != int64(12*Widthptr) {
                base.Fatalf("hash_iter size not correct %d %d", hiter.Width, 12*Widthptr)
@@ -332,9 +329,8 @@ func deferstruct(stksize int64) *types.Type {
        }
 
        // build struct holding the above fields
-       s := types.New(types.TSTRUCT)
+       s := types.NewStruct(fields)
        s.SetNoalg(true)
-       s.SetFields(fields)
        s.Width = widstruct(s, s, 0, 1)
        s.Align = uint8(Widthptr)
        return s
index 20ef3fc70a7dbfbb3e68463129bdacd8864a4b5a..2a0caad4693f3beeed2beaea7a1a5cdcf724b894 100644 (file)
@@ -2021,7 +2021,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                        return n
                }
 
-               if Curfn.Type().FuncType().Outnamed && n.List().Len() == 0 {
+               if hasNamedResults(Curfn) && n.List().Len() == 0 {
                        break
                }
                typecheckaste(ir.ORETURN, nil, false, Curfn.Type().Results(), n.List(), func() string { return "return argument" })
index b554674fbc6865c1357c22d1762295fab6a3115e..1c744dc36704297152f8734215c1c17c995a193b 100644 (file)
@@ -104,7 +104,7 @@ func initUniverse() {
        }
 
        types.Types[types.TANY] = types.New(types.TANY)
-       types.Types[types.TINTER] = types.New(types.TINTER) // empty interface
+       types.Types[types.TINTER] = types.NewInterface(nil)
 
        defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type {
                sym := pkg.Lookup(name)
@@ -325,15 +325,11 @@ func initUniverse() {
 }
 
 func makeErrorInterface() *types.Type {
-       sig := functypefield(fakeRecvField(), nil, []*types.Field{
+       sig := types.NewSignature(fakeRecvField(), nil, []*types.Field{
                types.NewField(src.NoXPos, nil, types.Types[types.TSTRING]),
        })
-
        method := types.NewField(src.NoXPos, lookup("Error"), sig)
-
-       t := types.New(types.TINTER)
-       t.SetInterface([]*types.Field{method})
-       return t
+       return types.NewInterface([]*types.Field{method})
 }
 
 // finishUniverse makes the universe block visible within the current package.
index be6f1539b93cd4289ba78295cb0a6e9d59ab1382..183a7acc1b5b33fba6da36f1ccebbd987489cef7 100644 (file)
@@ -274,7 +274,7 @@ func walkstmt(n ir.Node) ir.Node {
                if n.List().Len() == 0 {
                        break
                }
-               if (Curfn.Type().FuncType().Outnamed && n.List().Len() > 1) || paramoutheap(Curfn) {
+               if (hasNamedResults(Curfn) && n.List().Len() > 1) || paramoutheap(Curfn) {
                        // assign to the function out parameters,
                        // so that reorder3 can fix up conflicts
                        var rl []ir.Node
index 88a2fbba2f5eb8953f866bd6da582234c5c7d25d..72a35bc7daadce98c7de4ab3c159be7a0cbc250a 100644 (file)
@@ -24,7 +24,7 @@ func TestSizeof(t *testing.T) {
                {Type{}, 56, 96},
                {Map{}, 20, 40},
                {Forward{}, 20, 32},
-               {Func{}, 28, 48},
+               {Func{}, 24, 40},
                {Struct{}, 16, 32},
                {Interface{}, 8, 16},
                {Chan{}, 8, 16},
index 36aac53124b10bbfb10fc48ed54988a4f3453ddf..2eff8e3ba47f6eae4fb394fd2bd7b796957719c0 100644 (file)
@@ -285,8 +285,6 @@ type Func struct {
        // It gets calculated via a temporary TFUNCARGS type.
        // Note that TFUNC's Width is Widthptr.
        Argwid int64
-
-       Outnamed bool
 }
 
 // FuncType returns t's extra func-specific fields.
@@ -1618,3 +1616,60 @@ func NewBasic(kind Kind, obj Object) *Type {
        t.nod = obj
        return t
 }
+
+// NewInterface returns a new interface for the given methods and
+// embedded types. Embedded types are specified as fields with no Sym.
+func NewInterface(methods []*Field) *Type {
+       t := New(TINTER)
+       t.SetInterface(methods)
+       if anyBroke(methods) {
+               t.SetBroke(true)
+       }
+       return t
+}
+
+//  NewSignature returns a new function type for the given receiver,
+//  parameters, and results, any of which may be nil.
+func NewSignature(recv *Field, params, results []*Field) *Type {
+       var recvs []*Field
+       if recv != nil {
+               recvs = []*Field{recv}
+       }
+
+       t := New(TFUNC)
+       ft := t.FuncType()
+
+       funargs := func(fields []*Field, funarg Funarg) *Type {
+               s := NewStruct(fields)
+               s.StructType().Funarg = funarg
+               if s.Broke() {
+                       t.SetBroke(true)
+               }
+               return s
+       }
+
+       ft.Receiver = funargs(recvs, FunargRcvr)
+       ft.Params = funargs(params, FunargParams)
+       ft.Results = funargs(results, FunargResults)
+
+       return t
+}
+
+// NewStruct returns a new struct with the given fields.
+func NewStruct(fields []*Field) *Type {
+       t := New(TSTRUCT)
+       t.SetFields(fields)
+       if anyBroke(fields) {
+               t.SetBroke(true)
+       }
+       return t
+}
+
+func anyBroke(fields []*Field) bool {
+       for _, f := range fields {
+               if f.Broke() {
+                       return true
+               }
+       }
+       return false
+}