]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: make generated function code more consistent
authorMatthew Dempsky <mdempsky@google.com>
Thu, 19 Apr 2018 06:22:26 +0000 (23:22 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 20 Apr 2018 01:09:31 +0000 (01:09 +0000)
There are a bunch of places where we generate functions: equality and
hash functions; method expression and promoted method wrappers; and
print/delete wrappers for defer/go statements.

This CL brings them in sync by:

1) Always using dclfunc and funcbody. Most were already using this,
but makepartialcall needed some changes.

2) Removing duplicate types.Markdcl/types.Popdcl calls. These are
already handled by dclfunc and funcbody.

3) Using structargs (already used by genwrapper) to construct new
param/result lists from existing types.

4) Always accessing the parameter ONAME nodes through Field.Nname
instead of poking into the ODCLFIELD. Also, since creating a slice of
the entire parameter list is common, extract this out into a
paramNnames helper function.

5) Add a Type.IsVariadic method to simplify identifying variadic
function types.

Passes toolstash-check -gcflags=-dwarf=false. DWARF output changes
because using structargs in makepartialcall changes the generated
parameter names.

Change-Id: I6661d3699afdbe7852ad60db5a4ec6eeb2b696e4
Reviewed-on: https://go-review.googlesource.com/108216
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/alg.go
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/types/type.go

index b17cab68bd9d0b44288bfaf074127eb403f21f00..b7d88531fd7ca7f0dd1c19a03f95c673b804a113 100644 (file)
@@ -191,20 +191,18 @@ func genhash(sym *types.Sym, t *types.Type) {
 
        lineno = autogeneratedPos // less confusing than end of input
        dclcontext = PEXTERN
-       types.Markdcl()
 
        // func sym(p *T, h uintptr) uintptr
        tfn := nod(OTFUNC, nil, nil)
-       n := namedfield("p", types.NewPtr(t))
-       tfn.List.Append(n)
-       np := n.Left
-       n = namedfield("h", types.Types[TUINTPTR])
-       tfn.List.Append(n)
-       nh := n.Left
-       n = anonfield(types.Types[TUINTPTR]) // return value
-       tfn.Rlist.Append(n)
+       tfn.List.Set2(
+               namedfield("p", types.NewPtr(t)),
+               namedfield("h", types.Types[TUINTPTR]),
+       )
+       tfn.Rlist.Set1(anonfield(types.Types[TUINTPTR]))
 
        fn := dclfunc(sym, tfn)
+       np := asNode(tfn.Type.Params().Field(0).Nname)
+       nh := asNode(tfn.Type.Params().Field(1).Nname)
 
        // genhash is only called for types that have equality but
        // cannot be handled by the standard algorithms,
@@ -290,12 +288,14 @@ func genhash(sym *types.Sym, t *types.Type) {
        }
 
        funcbody()
-       Curfn = fn
+
        fn.Func.SetDupok(true)
        fn = typecheck(fn, Etop)
+
+       Curfn = fn
        typecheckslice(fn.Nbody.Slice(), Etop)
        Curfn = nil
-       types.Popdcl()
+
        if debug_dclstack != 0 {
                testdclstack()
        }
@@ -358,20 +358,18 @@ func geneq(sym *types.Sym, t *types.Type) {
 
        lineno = autogeneratedPos // less confusing than end of input
        dclcontext = PEXTERN
-       types.Markdcl()
 
        // func sym(p, q *T) bool
        tfn := nod(OTFUNC, nil, nil)
-       n := namedfield("p", types.NewPtr(t))
-       tfn.List.Append(n)
-       np := n.Left
-       n = namedfield("q", types.NewPtr(t))
-       tfn.List.Append(n)
-       nq := n.Left
-       n = anonfield(types.Types[TBOOL])
-       tfn.Rlist.Append(n)
+       tfn.List.Set2(
+               namedfield("p", types.NewPtr(t)),
+               namedfield("q", types.NewPtr(t)),
+       )
+       tfn.Rlist.Set1(anonfield(types.Types[TBOOL]))
 
        fn := dclfunc(sym, tfn)
+       np := asNode(tfn.Type.Params().Field(0).Nname)
+       nq := asNode(tfn.Type.Params().Field(1).Nname)
 
        // geneq is only called for types that have equality but
        // cannot be handled by the standard algorithms,
@@ -474,12 +472,14 @@ func geneq(sym *types.Sym, t *types.Type) {
        }
 
        funcbody()
-       Curfn = fn
+
        fn.Func.SetDupok(true)
        fn = typecheck(fn, Etop)
+
+       Curfn = fn
        typecheckslice(fn.Nbody.Slice(), Etop)
        Curfn = nil
-       types.Popdcl()
+
        if debug_dclstack != 0 {
                testdclstack()
        }
index 6a05bef3aae9baa901ee1abbd79590410e773b25..a0bf1e8cb954bc9c54182200734a3f6222802444 100644 (file)
@@ -91,7 +91,7 @@ func typecheckclosure(clo *Node, top int) {
        }
 
        xfunc.Func.Nname.Sym = closurename(Curfn)
-       xfunc.Func.Nname.Sym.SetOnExportList(true) // disable export
+       disableExport(xfunc.Func.Nname.Sym)
        declare(xfunc.Func.Nname, PFUNC)
        xfunc = typecheck(xfunc, Etop)
 
@@ -433,59 +433,24 @@ func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
        savecurfn := Curfn
        Curfn = nil
 
-       xtype := nod(OTFUNC, nil, nil)
-       var l []*Node
-       var callargs []*Node
-       ddd := false
-       xfunc := nod(ODCLFUNC, nil, nil)
-       Curfn = xfunc
-       for i, t := range t0.Params().Fields().Slice() {
-               n := newname(lookupN("a", i))
-               n.SetClass(PPARAM)
-               xfunc.Func.Dcl = append(xfunc.Func.Dcl, n)
-               callargs = append(callargs, n)
-               fld := nod(ODCLFIELD, n, typenod(t.Type))
-               if t.Isddd() {
-                       fld.SetIsddd(true)
-                       ddd = true
-               }
-
-               l = append(l, fld)
-       }
-
-       xtype.List.Set(l)
-       l = nil
-       var retargs []*Node
-       for i, t := range t0.Results().Fields().Slice() {
-               n := newname(lookupN("r", i))
-               n.SetClass(PPARAMOUT)
-               xfunc.Func.Dcl = append(xfunc.Func.Dcl, n)
-               retargs = append(retargs, n)
-               l = append(l, nod(ODCLFIELD, n, typenod(t.Type)))
-       }
-
-       xtype.Rlist.Set(l)
+       tfn := nod(OTFUNC, nil, nil)
+       tfn.List.Set(structargs(t0.Params(), true))
+       tfn.Rlist.Set(structargs(t0.Results(), false))
 
+       disableExport(sym)
+       xfunc := dclfunc(sym, tfn)
        xfunc.Func.SetDupok(true)
-       xfunc.Func.Nname = newfuncname(sym)
-       xfunc.Func.Nname.Sym.SetOnExportList(true) // disable export
-       xfunc.Func.Nname.Name.Param.Ntype = xtype
-       xfunc.Func.Nname.Name.Defn = xfunc
-       declare(xfunc.Func.Nname, PFUNC)
+       xfunc.Func.SetNeedctxt(true)
 
        // Declare and initialize variable holding receiver.
 
-       xfunc.Func.SetNeedctxt(true)
-
        cv := nod(OCLOSUREVAR, nil, nil)
        cv.Type = rcvrtype
        cv.Xoffset = Rnd(int64(Widthptr), int64(cv.Type.Align))
 
-       ptr := newname(lookup("rcvr"))
-       ptr.SetClass(PAUTO)
+       ptr := newname(lookup(".this"))
+       declare(ptr, PAUTO)
        ptr.Name.SetUsed(true)
-       ptr.Name.Curfn = xfunc
-       xfunc.Func.Dcl = append(xfunc.Func.Dcl, ptr)
        var body []*Node
        if rcvrtype.IsPtr() || rcvrtype.IsInterface() {
                ptr.Type = rcvrtype
@@ -496,20 +461,17 @@ func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
        }
 
        call := nod(OCALL, nodSym(OXDOT, ptr, meth), nil)
-       call.List.Set(callargs)
-       call.SetIsddd(ddd)
-       if t0.NumResults() == 0 {
-               body = append(body, call)
-       } else {
-               n := nod(OAS2, nil, nil)
-               n.List.Set(retargs)
-               n.Rlist.Set1(call)
-               body = append(body, n)
-               n = nod(ORETURN, nil, nil)
-               body = append(body, n)
+       call.List.Set(paramNnames(tfn.Type))
+       call.SetIsddd(tfn.Type.IsVariadic())
+       if t0.NumResults() != 0 {
+               n := nod(ORETURN, nil, nil)
+               n.List.Set1(call)
+               call = n
        }
+       body = append(body, call)
 
        xfunc.Nbody.Set(body)
+       funcbody()
 
        xfunc = typecheck(xfunc, Etop)
        sym.Def = asTypesNode(xfunc)
index 5db2c67d7f162f3bfe530d52dbe63a847b624113..0bb3c530f13e5d563fa4f65796544ad0c32178b7 100644 (file)
@@ -1026,6 +1026,12 @@ func makefuncsym(s *types.Sym) {
        }
 }
 
+// disableExport prevents sym from being included in package export
+// data. To be effectual, it must be called before declare.
+func disableExport(sym *types.Sym) {
+       sym.SetOnExportList(true)
+}
+
 func dclfunc(sym *types.Sym, tfn *Node) *Node {
        if tfn.Op != OTFUNC {
                Fatalf("expected OTFUNC node, got %v", tfn)
index 2f8f92271e2ee33ff37faefea58516fbeec47243..4d87f0da2612ae6a99a30852eeac2479ae1bd85a 100644 (file)
@@ -1639,31 +1639,18 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
        }
 
        lineno = autogeneratedPos
-
        dclcontext = PEXTERN
-       types.Markdcl()
-
-       this := namedfield(".this", rcvr)
-       this.Left.Name.Param.Ntype = this.Right
-       in := structargs(method.Type.Params(), true)
-       out := structargs(method.Type.Results(), false)
 
-       t := nod(OTFUNC, nil, nil)
-       t.List.Set(append([]*Node{this}, in...))
-       t.Rlist.Set(out)
+       tfn := nod(OTFUNC, nil, nil)
+       tfn.Left = namedfield(".this", rcvr)
+       tfn.List.Set(structargs(method.Type.Params(), true))
+       tfn.Rlist.Set(structargs(method.Type.Results(), false))
 
-       newnam.SetOnExportList(true) // prevent export; see closure.go
-       fn := dclfunc(newnam, t)
+       disableExport(newnam)
+       fn := dclfunc(newnam, tfn)
        fn.Func.SetDupok(true)
 
-       // arg list
-       var args []*Node
-
-       isddd := false
-       for _, n := range in {
-               args = append(args, n.Left)
-               isddd = n.Left.Isddd()
-       }
+       nthis := asNode(tfn.Type.Recv().Nname)
 
        methodrcvr := method.Type.Recv().Type
 
@@ -1671,13 +1658,13 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
        if rcvr.IsPtr() && rcvr.Elem() == methodrcvr {
                // generating wrapper from *T to T.
                n := nod(OIF, nil, nil)
-               n.Left = nod(OEQ, this.Left, nodnil())
+               n.Left = nod(OEQ, nthis, nodnil())
                call := nod(OCALL, syslook("panicwrap"), nil)
                n.Nbody.Set1(call)
                fn.Nbody.Append(n)
        }
 
-       dot := adddot(nodSym(OXDOT, this.Left, method.Sym))
+       dot := adddot(nodSym(OXDOT, nthis, method.Sym))
 
        // generate call
        // It's not possible to use a tail call when dynamic linking on ppc64le. The
@@ -1693,21 +1680,20 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
                if !dotlist[0].field.Type.IsPtr() {
                        dot = nod(OADDR, dot, nil)
                }
-               as := nod(OAS, this.Left, nod(OCONVNOP, dot, nil))
+               as := nod(OAS, nthis, nod(OCONVNOP, dot, nil))
                as.Right.Type = rcvr
                fn.Nbody.Append(as)
                fn.Nbody.Append(nodSym(ORETJMP, nil, methodSym(methodrcvr, method.Sym)))
        } else {
                fn.Func.SetWrapper(true) // ignore frame for panic+recover matching
                call := nod(OCALL, dot, nil)
-               call.List.Set(args)
-               call.SetIsddd(isddd)
+               call.List.Set(paramNnames(tfn.Type))
+               call.SetIsddd(tfn.Type.IsVariadic())
                if method.Type.NumResults() > 0 {
                        n := nod(ORETURN, nil, nil)
                        n.List.Set1(call)
                        call = n
                }
-
                fn.Nbody.Append(call)
        }
 
@@ -1716,17 +1702,13 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
        }
 
        funcbody()
-       Curfn = fn
-       types.Popdcl()
        if debug_dclstack != 0 {
                testdclstack()
        }
 
-       // wrappers where T is anonymous (struct or interface) can be duplicated.
-       if rcvr.IsStruct() || rcvr.IsInterface() || rcvr.IsPtr() && rcvr.Elem().IsStruct() {
-               fn.Func.SetDupok(true)
-       }
        fn = typecheck(fn, Etop)
+
+       Curfn = fn
        typecheckslice(fn.Nbody.Slice(), Etop)
 
        inlcalls(fn)
@@ -1736,6 +1718,14 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
        funccompile(fn)
 }
 
+func paramNnames(ft *types.Type) []*Node {
+       args := make([]*Node, ft.NumParams())
+       for i, f := range ft.Params().FieldSlice() {
+               args[i] = asNode(f.Nname)
+       }
+       return args
+}
+
 func hashmem(t *types.Type) *Node {
        sym := Runtimepkg.Lookup("memhash")
 
index c7c39232f4c987d753e9e9265944706bb99bf7fa..3ad18a17e34c7d691278a4c69fd7b4be77f741f4 100644 (file)
@@ -3861,12 +3861,9 @@ func wrapCall(n *Node, init *Nodes) *Node {
        }
 
        t := nod(OTFUNC, nil, nil)
-       var args []*Node
        for i, arg := range n.List.Slice() {
-               buf := fmt.Sprintf("a%d", i)
-               a := namedfield(buf, arg.Type)
-               t.List.Append(a)
-               args = append(args, a.Left)
+               s := lookupN("a", i)
+               t.List.Append(symfield(s, arg.Type))
        }
 
        wrapCall_prgen++
@@ -3874,7 +3871,7 @@ func wrapCall(n *Node, init *Nodes) *Node {
        fn := dclfunc(sym, t)
 
        a := nod(n.Op, nil, nil)
-       a.List.Set(args)
+       a.List.Set(paramNnames(t.Type))
        a = typecheck(a, Etop)
        fn.Nbody.Set1(a)
 
index f5e9237b81a30b53b08489d5cef980086cc3d1a0..55d0930ceb5566e0acbcaab27dcb14fe8da18cdf 100644 (file)
@@ -710,6 +710,12 @@ func (t *Type) NumRecvs() int   { return t.FuncType().Receiver.NumFields() }
 func (t *Type) NumParams() int  { return t.FuncType().Params.NumFields() }
 func (t *Type) NumResults() int { return t.FuncType().Results.NumFields() }
 
+// IsVariadic reports whether function type t is variadic.
+func (t *Type) IsVariadic() bool {
+       n := t.NumParams()
+       return n > 0 && t.Params().Field(n-1).Isddd()
+}
+
 // Recv returns the receiver of function type t, if any.
 func (t *Type) Recv() *Field {
        s := t.Recvs()