[dev.regabi] cmd/compile: add ir.CallPartExpr

Now there are no longer any generic nodes with a non-nil
associated Func, so node.fn can be deleted. Also all manipulation
of func fields is done with concrete types, so Node.SetFunc can be
deleted, along with generic implementations.

Passes buildall w/ toolstash -cmp.

Change-Id: I4fee99870951ec9dc224f146d87b22e2bfe16889
Reviewed-on: https://go-review.googlesource.com/c/go/+/274099
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-11-26 01:05:39 -05:00
parent 4eaef981b5
commit e5c6463e20
9 changed files with 40 additions and 21 deletions

View File

@ -414,7 +414,7 @@ func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node {
return walkexpr(clos, init) return walkexpr(clos, init)
} }
func typecheckpartialcall(dot ir.Node, sym *types.Sym) { func typecheckpartialcall(dot ir.Node, sym *types.Sym) *ir.CallPartExpr {
switch dot.Op() { switch dot.Op() {
case ir.ODOTINTER, ir.ODOTMETH: case ir.ODOTINTER, ir.ODOTMETH:
break break
@ -427,11 +427,7 @@ func typecheckpartialcall(dot ir.Node, sym *types.Sym) {
fn := makepartialcall(dot, dot.Type(), sym) fn := makepartialcall(dot, dot.Type(), sym)
fn.SetWrapper(true) fn.SetWrapper(true)
dot.SetOp(ir.OCALLPART) return ir.NewCallPartExpr(dot.Pos(), dot.Left(), NewName(sym), fn)
dot.SetRight(NewName(sym))
dot.SetType(fn.Type())
dot.SetFunc(fn)
dot.SetOpt(nil) // clear types.Field from ODOTMETH
} }
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed // makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
@ -522,7 +518,7 @@ func partialCallType(n ir.Node) *types.Type {
return t return t
} }
func walkpartialcall(n ir.Node, init *ir.Nodes) ir.Node { func walkpartialcall(n *ir.CallPartExpr, init *ir.Nodes) ir.Node {
// Create closure in the form of a composite literal. // Create closure in the form of a composite literal.
// For x.M with receiver (x) type T, the generated code looks like: // For x.M with receiver (x) type T, the generated code looks like:
// //

View File

@ -795,7 +795,7 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy
// - msym is the method symbol // - msym is the method symbol
// - t is function type (with receiver) // - t is function type (with receiver)
// Returns a pointer to the existing or added Field; or nil if there's an error. // Returns a pointer to the existing or added Field; or nil if there's an error.
func addmethod(n ir.Node, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field { func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field {
if msym == nil { if msym == nil {
base.Fatalf("no method symbol") base.Fatalf("no method symbol")
} }

View File

@ -4146,10 +4146,14 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder {
} }
func isIntrinsicCall(n ir.Node) bool { func isIntrinsicCall(n ir.Node) bool {
if n == nil || n.Left() == nil { if n == nil {
return false return false
} }
return findIntrinsic(n.Left().Sym()) != nil name, ok := n.Left().(*ir.Name)
if !ok {
return false
}
return findIntrinsic(name.Sym()) != nil
} }
// intrinsicCall converts a call to a recognized intrinsic function into the intrinsic SSA operation. // intrinsicCall converts a call to a recognized intrinsic function into the intrinsic SSA operation.

View File

@ -964,7 +964,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
if top&ctxCallee != 0 { if top&ctxCallee != 0 {
ok |= ctxCallee ok |= ctxCallee
} else { } else {
typecheckpartialcall(n, s) n = typecheckpartialcall(n, s)
ok |= ctxExpr ok |= ctxExpr
} }

View File

@ -1578,7 +1578,7 @@ opswitch:
n = walkclosure(n, init) n = walkclosure(n, init)
case ir.OCALLPART: case ir.OCALLPART:
n = walkpartialcall(n, init) n = walkpartialcall(n.(*ir.CallPartExpr), init)
} }
// Expressions that are constant at run time but not // Expressions that are constant at run time but not

View File

@ -84,3 +84,29 @@ func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *ClosureRead) RawCopy() Node { c := *n; return &c } func (n *ClosureRead) RawCopy() Node { c := *n; return &c }
func (n *ClosureRead) Type() *types.Type { return n.typ } func (n *ClosureRead) Type() *types.Type { return n.typ }
func (n *ClosureRead) Offset() int64 { return n.offset } func (n *ClosureRead) Offset() int64 { return n.offset }
// A CallPartExpr is a method expression X.Method (uncalled).
type CallPartExpr struct {
miniExpr
fn *Func
X Node
Method *Name
}
func NewCallPartExpr(pos src.XPos, x Node, method *Name, fn *Func) *CallPartExpr {
n := &CallPartExpr{fn: fn, X: x, Method: method}
n.op = OCALLPART
n.pos = pos
n.typ = fn.Type()
n.fn = fn
return n
}
func (n *CallPartExpr) String() string { return fmt.Sprint(n) }
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) Func() *Func { return n.fn }
func (n *CallPartExpr) Left() Node { return n.X }
func (n *CallPartExpr) Right() Node { return n.Method }
func (n *CallPartExpr) SetLeft(x Node) { n.X = x }
func (n *CallPartExpr) SetRight(x Node) { n.Method = x.(*Name) }

View File

@ -128,7 +128,6 @@ func (n *miniNode) SetSubOp(Op) { panic(n.no("SetSubOp")) }
func (n *miniNode) Type() *types.Type { return nil } func (n *miniNode) Type() *types.Type { return nil }
func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) } func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) }
func (n *miniNode) Func() *Func { return nil } func (n *miniNode) Func() *Func { return nil }
func (n *miniNode) SetFunc(*Func) { panic(n.no("SetFunc")) }
func (n *miniNode) Name() *Name { return nil } func (n *miniNode) Name() *Name { return nil }
func (n *miniNode) Sym() *types.Sym { return nil } func (n *miniNode) Sym() *types.Sym { return nil }
func (n *miniNode) SetSym(*types.Sym) { panic(n.no("SetSym")) } func (n *miniNode) SetSym(*types.Sym) { panic(n.no("SetSym")) }

View File

@ -56,7 +56,6 @@ type Node interface {
Type() *types.Type Type() *types.Type
SetType(t *types.Type) SetType(t *types.Type)
Func() *Func Func() *Func
SetFunc(x *Func)
Name() *Name Name() *Name
Sym() *types.Sym Sym() *types.Sym
SetSym(x *types.Sym) SetSym(x *types.Sym)
@ -143,9 +142,6 @@ type node struct {
typ *types.Type typ *types.Type
orig Node // original form, for printing, and tracking copies of ONAMEs orig Node // original form, for printing, and tracking copies of ONAMEs
// func
fn *Func
sym *types.Sym // various sym *types.Sym // various
opt interface{} opt interface{}
@ -177,8 +173,7 @@ func (n *node) Orig() Node { return n.orig }
func (n *node) SetOrig(x Node) { n.orig = x } func (n *node) SetOrig(x Node) { n.orig = x }
func (n *node) Type() *types.Type { return n.typ } func (n *node) Type() *types.Type { return n.typ }
func (n *node) SetType(x *types.Type) { n.typ = x } func (n *node) SetType(x *types.Type) { n.typ = x }
func (n *node) Func() *Func { return n.fn } func (n *node) Func() *Func { return nil }
func (n *node) SetFunc(x *Func) { n.fn = x }
func (n *node) Name() *Name { return nil } func (n *node) Name() *Name { return nil }
func (n *node) Sym() *types.Sym { return n.sym } func (n *node) Sym() *types.Sym { return n.sym }
func (n *node) SetSym(x *types.Sym) { n.sym = x } func (n *node) SetSym(x *types.Sym) { n.sym = x }
@ -1156,7 +1151,6 @@ var okForNod = [OEND]bool{
OCALLFUNC: true, OCALLFUNC: true,
OCALLINTER: true, OCALLINTER: true,
OCALLMETH: true, OCALLMETH: true,
OCALLPART: true,
OCAP: true, OCAP: true,
OCASE: true, OCASE: true,
OCFUNC: true, OCFUNC: true,

View File

@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) {
}{ }{
{Func{}, 168, 288}, {Func{}, 168, 288},
{Name{}, 128, 224}, {Name{}, 128, 224},
{node{}, 84, 144}, {node{}, 80, 136},
} }
for _, tt := range tests { for _, tt := range tests {