]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile/internal/gc: add MethodName for getting referenced method
authorMatthew Dempsky <mdempsky@google.com>
Sun, 22 Nov 2020 21:47:55 +0000 (13:47 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 24 Nov 2020 01:34:13 +0000 (01:34 +0000)
A common operation throughout the front end is getting the ONAME for a
method used in a method selector, method expression, or method value.
This CL adds MethodName as a uniform API for doing this for all of
these kinds of nodes.

For method selectors (ODOTMETH) and method expressions (ONAMEs where
isMethodExpression reports true), we take advantage of the Node.Opt
field to save the types.Field. This is the approach we already started
taking in golang.org/cl/271217 (caching types.Field in Node.Opt for
ODOT).

For method values (OCALLPART), we continue using the existing
callpartMethod helper function. Escape analysis already uses Node.Opt
for tracking the method value's closure's data flow.

A subsequent, automated refactoring CL will make more use of this
method. For now, we just address a few cases in inl.go that aren't
easily automated.

Passes toolstash-check.

Change-Id: Ic92b288b2d8b2fa7e18e3b68634326b8ef0d869b
Reviewed-on: https://go-review.googlesource.com/c/go/+/272387
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/fmtmap_test.go
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/typecheck.go

index 0811df7f7b80074ede902181944f703c5dc89968..a8698de3079314c594ea51f48401e1cdf526fa09 100644 (file)
@@ -50,7 +50,6 @@ var knownFormats = map[string]string{
        "*cmd/compile/internal/types.Sym %v":              "",
        "*cmd/compile/internal/types.Type %#L":            "",
        "*cmd/compile/internal/types.Type %#v":            "",
-       "*cmd/compile/internal/types.Type %+v":            "",
        "*cmd/compile/internal/types.Type %-S":            "",
        "*cmd/compile/internal/types.Type %0S":            "",
        "*cmd/compile/internal/types.Type %L":             "",
index 42a9b4f3e88763fddf5517e9ef501f7ea9150a7b..dd6640667de8b978c53c5984164aafaebbf057cd 100644 (file)
@@ -435,6 +435,7 @@ func typecheckpartialcall(fn *Node, sym *types.Sym) {
        fn.Right = newname(sym)
        fn.Op = OCALLPART
        fn.Type = xfunc.Type
+       fn.SetOpt(nil) // clear types.Field from ODOTMETH
 }
 
 // makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
index 419056985fc1446c9ee7906db345a7db32c22e8d..1fab67391bd094397f2c45af1656592b80926d3e 100644 (file)
@@ -358,9 +358,6 @@ func (v *hairyVisitor) visit(n *Node) bool {
                if t == nil {
                        Fatalf("no function type for [%p] %+v\n", n.Left, n.Left)
                }
-               if t.Nname() == nil {
-                       Fatalf("no function definition for [%p] %+v\n", t, t)
-               }
                if isRuntimePkg(n.Left.Sym.Pkg) {
                        fn := n.Left.Sym.Name
                        if fn == "heapBits.nextArena" {
@@ -372,7 +369,7 @@ func (v *hairyVisitor) visit(n *Node) bool {
                                break
                        }
                }
-               if inlfn := asNode(t.FuncType().Nname).Func; inlfn.Inl != nil {
+               if inlfn := n.Left.MethodName().Func; inlfn.Inl != nil {
                        v.budget -= inlfn.Inl.Cost
                        break
                }
@@ -703,11 +700,7 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node {
                        Fatalf("no function type for [%p] %+v\n", n.Left, n.Left)
                }
 
-               if n.Left.Type.Nname() == nil {
-                       Fatalf("no function definition for [%p] %+v\n", n.Left.Type, n.Left.Type)
-               }
-
-               n = mkinlcall(n, asNode(n.Left.Type.FuncType().Nname), maxCost, inlMap)
+               n = mkinlcall(n, n.Left.MethodName(), maxCost, inlMap)
        }
 
        lineno = lno
index 43358333b82e7dc062fc6f4cf8c378f7702d5ccd..e46a0dadf3fa7deb0a027eafb58e546a29e08b48 100644 (file)
@@ -266,7 +266,11 @@ func (n *Node) Opt() interface{} {
 // SetOpt sets the optimizer data for the node, which must not have been used with SetVal.
 // SetOpt(nil) is ignored for Vals to simplify call sites that are clearing Opts.
 func (n *Node) SetOpt(x interface{}) {
-       if x == nil && n.HasVal() {
+       if x == nil {
+               if n.HasOpt() {
+                       n.SetHasOpt(false)
+                       n.E = nil
+               }
                return
        }
        if n.HasVal() {
index c0b05035f033c1f1b6b6a54868ab2e2476471522..1c371c0e9daafc1c8ac5a0532862dd0c160a939f 100644 (file)
@@ -2416,6 +2416,7 @@ func typecheckMethodExpr(n *Node) (res *Node) {
        n.Type = methodfunc(m.Type, n.Left.Type)
        n.Xoffset = 0
        n.SetClass(PFUNC)
+       n.SetOpt(m)
        // methodSym already marked n.Sym as a function.
 
        // Issue 25065. Make sure that we emit the symbol for a local method.
@@ -2538,6 +2539,7 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
                n.Xoffset = f2.Offset
                n.Type = f2.Type
                n.Op = ODOTMETH
+               n.SetOpt(f2)
 
                return f2
        }
@@ -4017,3 +4019,22 @@ func curpkg() *types.Pkg {
 
        return fnpkg(fn)
 }
+
+// MethodName returns the ONAME representing the method
+// referenced by expression n, which must be a method selector,
+// method expression, or method value.
+func (n *Node) MethodName() *Node {
+       return asNode(n.MethodFunc().Type.Nname())
+}
+
+// MethodFunc is like MethodName, but returns the types.Field instead.
+func (n *Node) MethodFunc() *types.Field {
+       switch {
+       case n.Op == ODOTMETH || n.isMethodExpression():
+               return n.Opt().(*types.Field)
+       case n.Op == OCALLPART:
+               return callpartMethod(n)
+       }
+       Fatalf("unexpected node: %v (%v)", n, n.Op)
+       panic("unreachable")
+}