1
0
mirror of https://github.com/golang/go synced 2024-11-11 23:20:24 -07:00

[dev.regabi] cmd/compile/internal/gc: add MethodName for getting referenced method

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>
This commit is contained in:
Matthew Dempsky 2020-11-22 13:47:55 -08:00
parent e1047302bd
commit b30c7a8044
5 changed files with 29 additions and 11 deletions

View 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": "",

View 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

View 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

View 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() {

View 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")
}