[dev.regabi] cmd/compile: store types.Field on {Selector,CallPart}Expr

It's useful to have quick access to the types.Field that a given
selector or method value expression refer to. Previously we abused Opt
for this, but couldn't do that for OCALLPART because escape analysis
uses Opt.

Now that we have more flexibility, we can simply add additional
pointer fields for this. This also allows getting rid of an unneeded
ONAME node for OCALLPART.

Passes buildall w/ toolstash -cmp.

Change-Id: I980d7bdb19abfd0b6f58a232876861b88dee1e47
Reviewed-on: https://go-review.googlesource.com/c/go/+/275034
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2020-12-02 21:38:20 -08:00
parent a2058bac21
commit 351bc2f38c
7 changed files with 24 additions and 32 deletions

View file

@ -427,7 +427,7 @@ func typecheckpartialcall(dot ir.Node, sym *types.Sym) *ir.CallPartExpr {
fn := makepartialcall(dot, dot.Type(), sym) fn := makepartialcall(dot, dot.Type(), sym)
fn.SetWrapper(true) fn.SetWrapper(true)
return ir.NewCallPartExpr(dot.Pos(), dot.Left(), NewName(sym), fn) return ir.NewCallPartExpr(dot.Pos(), dot.Left(), dot.(*ir.SelectorExpr).Selection, fn)
} }
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed // makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
@ -565,16 +565,5 @@ func walkpartialcall(n *ir.CallPartExpr, init *ir.Nodes) ir.Node {
// callpartMethod returns the *types.Field representing the method // callpartMethod returns the *types.Field representing the method
// referenced by method value n. // referenced by method value n.
func callpartMethod(n ir.Node) *types.Field { func callpartMethod(n ir.Node) *types.Field {
if n.Op() != ir.OCALLPART { return n.(*ir.CallPartExpr).Method
base.Fatalf("expected OCALLPART, got %v", n)
}
// TODO(mdempsky): Optimize this. If necessary,
// makepartialcall could save m for us somewhere.
var m *types.Field
if lookdot0(n.Right().Sym(), n.Left().Type(), &m, false) != 1 {
base.Fatalf("failed to find field for OCALLPART")
}
return m
} }

View file

@ -1290,8 +1290,7 @@ func (w *exportWriter) expr(n ir.Node) {
w.op(ir.OXDOT) w.op(ir.OXDOT)
w.pos(n.Pos()) w.pos(n.Pos())
w.expr(n.Left()) w.expr(n.Left())
// Right node should be ONAME w.selector(n.Sym())
w.selector(n.Right().Sym())
case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH: case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH:
w.op(ir.OXDOT) w.op(ir.OXDOT)

View file

@ -430,6 +430,9 @@ func (v *hairyVisitor) visit(n ir.Node) bool {
// In any event, let the visitList(n.List()) below take care of the statements, // In any event, let the visitList(n.List()) below take care of the statements,
// and don't charge for the OBLOCK itself. The ++ undoes the -- below. // and don't charge for the OBLOCK itself. The ++ undoes the -- below.
v.budget++ v.budget++
case ir.OCALLPART:
v.budget-- // Hack for toolstash -cmp.
} }
v.budget-- v.budget--

View file

@ -2385,7 +2385,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) {
me.SetType(methodfunc(m.Type, n.Left().Type())) me.SetType(methodfunc(m.Type, n.Left().Type()))
me.SetOffset(0) me.SetOffset(0)
me.SetClass(ir.PFUNC) me.SetClass(ir.PFUNC)
me.SetOpt(m) me.(*ir.MethodExpr).Method = m
// Issue 25065. Make sure that we emit the symbol for a local method. // Issue 25065. Make sure that we emit the symbol for a local method.
if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == ir.LocalPkg) { if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == ir.LocalPkg) {
@ -2448,10 +2448,8 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field {
} }
n.SetOp(ir.ODOTINTER) n.SetOp(ir.ODOTINTER)
} else {
n.SetOpt(f1)
} }
n.(*ir.SelectorExpr).Selection = f1
return f1 return f1
} }
@ -2507,7 +2505,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field {
n.SetOffset(f2.Offset) n.SetOffset(f2.Offset)
n.SetType(f2.Type) n.SetType(f2.Type)
n.SetOp(ir.ODOTMETH) n.SetOp(ir.ODOTMETH)
n.SetOpt(f2) n.(*ir.SelectorExpr).Selection = f2
return f2 return f2
} }
@ -3933,8 +3931,10 @@ func methodExprName(n ir.Node) *ir.Name {
// MethodFunc is like MethodName, but returns the types.Field instead. // MethodFunc is like MethodName, but returns the types.Field instead.
func methodExprFunc(n ir.Node) *types.Field { func methodExprFunc(n ir.Node) *types.Field {
switch n.Op() { switch n.Op() {
case ir.ODOTMETH, ir.OMETHEXPR: case ir.ODOTMETH:
return n.Opt().(*types.Field) return n.(*ir.SelectorExpr).Selection
case ir.OMETHEXPR:
return n.(*ir.MethodExpr).Method
case ir.OCALLPART: case ir.OCALLPART:
return callpartMethod(n) return callpartMethod(n)
} }

View file

@ -3757,7 +3757,7 @@ func usefield(n ir.Node) {
if t.IsPtr() { if t.IsPtr() {
t = t.Elem() t = t.Elem()
} }
field := n.Opt().(*types.Field) field := n.(*ir.SelectorExpr).Selection
if field == nil { if field == nil {
base.Fatalf("usefield %v %v without paramfld", n.Left().Type(), n.Sym()) base.Fatalf("usefield %v %v without paramfld", n.Left().Type(), n.Sym())
} }

View file

@ -205,10 +205,10 @@ type CallPartExpr struct {
miniExpr miniExpr
fn *Func fn *Func
X Node X Node
Method *Name Method *types.Field
} }
func NewCallPartExpr(pos src.XPos, x Node, method *Name, fn *Func) *CallPartExpr { func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr {
n := &CallPartExpr{fn: fn, X: x, Method: method} n := &CallPartExpr{fn: fn, X: x, Method: method}
n.op = OCALLPART n.op = OCALLPART
n.pos = pos n.pos = pos
@ -222,9 +222,8 @@ func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *CallPartExpr) rawCopy() Node { c := *n; return &c } func (n *CallPartExpr) rawCopy() Node { c := *n; return &c }
func (n *CallPartExpr) Func() *Func { return n.fn } func (n *CallPartExpr) Func() *Func { return n.fn }
func (n *CallPartExpr) Left() Node { return n.X } func (n *CallPartExpr) Left() Node { return n.X }
func (n *CallPartExpr) Right() Node { return n.Method } func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym }
func (n *CallPartExpr) SetLeft(x Node) { n.X = x } func (n *CallPartExpr) SetLeft(x Node) { n.X = x }
func (n *CallPartExpr) SetRight(x Node) { n.Method = x.(*Name) }
// A ClosureExpr is a function literal expression. // A ClosureExpr is a function literal expression.
type ClosureExpr struct { type ClosureExpr struct {
@ -499,6 +498,7 @@ type MethodExpr struct {
sym *types.Sym sym *types.Sym
offset int64 offset int64
class Class class Class
Method *types.Field
} }
func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr { func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr {
@ -596,9 +596,10 @@ func (n *ResultExpr) SetOffset(x int64) { n.offset = x }
// A SelectorExpr is a selector expression X.Sym. // A SelectorExpr is a selector expression X.Sym.
type SelectorExpr struct { type SelectorExpr struct {
miniExpr miniExpr
X Node X Node
Sel *types.Sym Sel *types.Sym
offset int64 offset int64
Selection *types.Field
} }
func NewSelectorExpr(pos src.XPos, x Node, sel *types.Sym) *SelectorExpr { func NewSelectorExpr(pos src.XPos, x Node, sel *types.Sym) *SelectorExpr {

View file

@ -1382,11 +1382,11 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
case OCALLPART: case OCALLPART:
exprFmt(n.Left(), s, nprec, mode) exprFmt(n.Left(), s, nprec, mode)
if n.Right() == nil || n.Right().Sym() == nil { if n.Sym() == nil {
fmt.Fprint(s, ".<nil>") fmt.Fprint(s, ".<nil>")
return return
} }
mode.Fprintf(s, ".%0S", n.Right().Sym()) mode.Fprintf(s, ".%0S", n.Sym())
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
exprFmt(n.Left(), s, nprec, mode) exprFmt(n.Left(), s, nprec, mode)