[dev.regabi] cmd/compile: only access Func method on concrete types

Sets up for removing Func from Node interface.
That means that once the Name reorg is done,
which will let us remove Name, Sym, and Val,
Node will be basically a minimal interface.

Passes buildall w/ toolstash -cmp.

Change-Id: I6e87897572debd7f8e29b4f5167763dc2792b408
Reviewed-on: https://go-review.googlesource.com/c/go/+/279484
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-12-21 15:10:26 -05:00
parent 51ba53f5c2
commit 280e7fd1ee
14 changed files with 63 additions and 25 deletions

View file

@ -76,7 +76,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
// function associated with the closure. // function associated with the closure.
// TODO: This creation of the named function should probably really be done in a // TODO: This creation of the named function should probably really be done in a
// separate pass from type-checking. // separate pass from type-checking.
func typecheckclosure(clo ir.Node, top int) { func typecheckclosure(clo *ir.ClosureExpr, top int) {
fn := clo.Func() fn := clo.Func()
// Set current associated iota value, so iota can be used inside // Set current associated iota value, so iota can be used inside
// function in ConstSpec, see issue #22344 // function in ConstSpec, see issue #22344
@ -327,13 +327,13 @@ func transformclosure(fn *ir.Func) {
// hasemptycvars reports whether closure clo has an // hasemptycvars reports whether closure clo has an
// empty list of captured vars. // empty list of captured vars.
func hasemptycvars(clo ir.Node) bool { func hasemptycvars(clo *ir.ClosureExpr) bool {
return len(clo.Func().ClosureVars) == 0 return len(clo.Func().ClosureVars) == 0
} }
// closuredebugruntimecheck applies boilerplate checks for debug flags // closuredebugruntimecheck applies boilerplate checks for debug flags
// and compiling runtime // and compiling runtime
func closuredebugruntimecheck(clo ir.Node) { func closuredebugruntimecheck(clo *ir.ClosureExpr) {
if base.Debug.Closure > 0 { if base.Debug.Closure > 0 {
if clo.Esc() == EscHeap { if clo.Esc() == EscHeap {
base.WarnfAt(clo.Pos(), "heap closure, captured vars = %v", clo.Func().ClosureVars) base.WarnfAt(clo.Pos(), "heap closure, captured vars = %v", clo.Func().ClosureVars)
@ -349,7 +349,7 @@ func closuredebugruntimecheck(clo ir.Node) {
// closureType returns the struct type used to hold all the information // closureType returns the struct type used to hold all the information
// needed in the closure for clo (clo must be a OCLOSURE node). // needed in the closure for clo (clo must be a OCLOSURE node).
// The address of a variable of the returned type can be cast to a func. // The address of a variable of the returned type can be cast to a func.
func closureType(clo ir.Node) *types.Type { func closureType(clo *ir.ClosureExpr) *types.Type {
// Create closure in the form of a composite literal. // Create closure in the form of a composite literal.
// supposing the closure captures an int i and a string s // supposing the closure captures an int i and a string s
// and has one float64 argument and no results, // and has one float64 argument and no results,

View file

@ -892,6 +892,7 @@ func (c *nowritebarrierrecChecker) findExtraCalls(nn ir.Node) {
case ir.ONAME: case ir.ONAME:
callee = arg.Name().Defn.(*ir.Func) callee = arg.Name().Defn.(*ir.Func)
case ir.OCLOSURE: case ir.OCLOSURE:
arg := arg.(*ir.ClosureExpr)
callee = arg.Func() callee = arg.Func()
default: default:
base.Fatalf("expected ONAME or OCLOSURE node, got %+v", arg) base.Fatalf("expected ONAME or OCLOSURE node, got %+v", arg)

View file

@ -678,6 +678,7 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) {
} }
case ir.OCLOSURE: case ir.OCLOSURE:
n := n.(*ir.ClosureExpr)
k = e.spill(k, n) k = e.spill(k, n)
// Link addresses of captured variables to closure. // Link addresses of captured variables to closure.
@ -879,7 +880,7 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) {
case v.Op() == ir.ONAME && v.(*ir.Name).Class() == ir.PFUNC: case v.Op() == ir.ONAME && v.(*ir.Name).Class() == ir.PFUNC:
fn = v.(*ir.Name) fn = v.(*ir.Name)
case v.Op() == ir.OCLOSURE: case v.Op() == ir.OCLOSURE:
fn = v.Func().Nname fn = v.(*ir.ClosureExpr).Func().Nname
} }
case ir.OCALLMETH: case ir.OCALLMETH:
fn = methodExprName(call.Left()) fn = methodExprName(call.Left())
@ -1883,7 +1884,7 @@ func heapAllocReason(n ir.Node) string {
return "too large for stack" return "too large for stack"
} }
if n.Op() == ir.OCLOSURE && closureType(n).Size() >= maxImplicitStackVarSize { if n.Op() == ir.OCLOSURE && closureType(n.(*ir.ClosureExpr)).Size() >= maxImplicitStackVarSize {
return "too large for stack" return "too large for stack"
} }
if n.Op() == ir.OCALLPART && partialCallType(n.(*ir.CallPartExpr)).Size() >= maxImplicitStackVarSize { if n.Op() == ir.OCALLPART && partialCallType(n.(*ir.CallPartExpr)).Size() >= maxImplicitStackVarSize {

View file

@ -630,7 +630,7 @@ func (r *importReader) varExt(n ir.Node) {
r.symIdx(n.Sym()) r.symIdx(n.Sym())
} }
func (r *importReader) funcExt(n ir.Node) { func (r *importReader) funcExt(n *ir.Name) {
r.linkname(n.Sym()) r.linkname(n.Sym())
r.symIdx(n.Sym()) r.symIdx(n.Sym())
@ -654,7 +654,7 @@ func (r *importReader) methExt(m *types.Field) {
if r.bool() { if r.bool() {
m.SetNointerface(true) m.SetNointerface(true)
} }
r.funcExt(ir.AsNode(m.Nname)) r.funcExt(m.Nname.(*ir.Name))
} }
func (r *importReader) linkname(s *types.Sym) { func (r *importReader) linkname(s *types.Sym) {

View file

@ -296,6 +296,7 @@ func (d *initDeps) visit(n ir.Node) {
} }
case ir.OCLOSURE: case ir.OCLOSURE:
n := n.(*ir.ClosureExpr)
d.inspectList(n.Func().Body()) d.inspectList(n.Func().Body())
case ir.ODOTMETH, ir.OCALLPART: case ir.ODOTMETH, ir.OCALLPART:

View file

@ -237,7 +237,7 @@ func caninl(fn *ir.Func) {
n.Func().Inl = &ir.Inline{ n.Func().Inl = &ir.Inline{
Cost: inlineMaxBudget - visitor.budget, Cost: inlineMaxBudget - visitor.budget,
Dcl: pruneUnusedAutos(n.Defn.Func().Dcl, &visitor), Dcl: pruneUnusedAutos(n.Defn.(*ir.Func).Func().Dcl, &visitor),
Body: ir.DeepCopyList(src.NoXPos, fn.Body().Slice()), Body: ir.DeepCopyList(src.NoXPos, fn.Body().Slice()),
} }
@ -677,6 +677,7 @@ func inlCallee(fn ir.Node) *ir.Func {
return fn.Func() return fn.Func()
} }
case ir.OCLOSURE: case ir.OCLOSURE:
fn := fn.(*ir.ClosureExpr)
c := fn.Func() c := fn.Func()
caninl(c) caninl(c)
return c return c

View file

@ -270,9 +270,12 @@ func Main(archInit func(*Arch)) {
// before walk reaches a call of a closure. // before walk reaches a call of a closure.
timings.Start("fe", "xclosures") timings.Start("fe", "xclosures")
for _, n := range Target.Decls { for _, n := range Target.Decls {
if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil { if n.Op() == ir.ODCLFUNC {
Curfn = n.(*ir.Func) n := n.(*ir.Func)
transformclosure(Curfn) if n.Func().OClosure != nil {
Curfn = n
transformclosure(n)
}
} }
} }

View file

@ -56,8 +56,11 @@ func visitBottomUp(list []ir.Node, analyze func(list []*ir.Func, recursive bool)
v.analyze = analyze v.analyze = analyze
v.nodeID = make(map[*ir.Func]uint32) v.nodeID = make(map[*ir.Func]uint32)
for _, n := range list { for _, n := range list {
if n.Op() == ir.ODCLFUNC && !n.Func().IsHiddenClosure() { if n.Op() == ir.ODCLFUNC {
v.visit(n.(*ir.Func)) n := n.(*ir.Func)
if !n.Func().IsHiddenClosure() {
v.visit(n)
}
} }
} }
} }
@ -109,6 +112,7 @@ func (v *bottomUpVisitor) visit(n *ir.Func) uint32 {
} }
} }
case ir.OCLOSURE: case ir.OCLOSURE:
n := n.(*ir.ClosureExpr)
if m := v.visit(n.Func()); m < min { if m := v.visit(n.Func()); m < min {
min = m min = m
} }

View file

@ -28,7 +28,7 @@ func findScope(marks []ir.Mark, pos src.XPos) ir.ScopeID {
return marks[i-1].Scope return marks[i-1].Scope
} }
func assembleScopes(fnsym *obj.LSym, fn ir.Node, dwarfVars []*dwarf.Var, varScopes []ir.ScopeID) []dwarf.Scope { func assembleScopes(fnsym *obj.LSym, fn *ir.Func, dwarfVars []*dwarf.Var, varScopes []ir.ScopeID) []dwarf.Scope {
// Initialize the DWARF scope tree based on lexical scopes. // Initialize the DWARF scope tree based on lexical scopes.
dwarfScopes := make([]dwarf.Scope, 1+len(fn.Func().Parents)) dwarfScopes := make([]dwarf.Scope, 1+len(fn.Func().Parents))
for i, parent := range fn.Func().Parents { for i, parent := range fn.Func().Parents {

View file

@ -269,6 +269,7 @@ func (s *InitSchedule) staticassign(l *ir.Name, loff int64, r ir.Node, typ *type
break break
case ir.OCLOSURE: case ir.OCLOSURE:
r := r.(*ir.ClosureExpr)
if hasemptycvars(r) { if hasemptycvars(r) {
if base.Debug.Closure > 0 { if base.Debug.Closure > 0 {
base.WarnfAt(r.Pos(), "closure converted to global") base.WarnfAt(r.Pos(), "closure converted to global")

View file

@ -95,9 +95,12 @@ func TypecheckPackage() {
// because variables captured by value do not escape. // because variables captured by value do not escape.
timings.Start("fe", "capturevars") timings.Start("fe", "capturevars")
for _, n := range Target.Decls { for _, n := range Target.Decls {
if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil { if n.Op() == ir.ODCLFUNC {
Curfn = n.(*ir.Func) n := n.(*ir.Func)
capturevars(Curfn) if n.Func().OClosure != nil {
Curfn = n
capturevars(n)
}
} }
} }
capturevarscomplete = true capturevarscomplete = true
@ -2078,6 +2081,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n return n
case ir.OCLOSURE: case ir.OCLOSURE:
n := n.(*ir.ClosureExpr)
typecheckclosure(n, top) typecheckclosure(n, top)
if n.Type() == nil { if n.Type() == nil {
return n return n

View file

@ -649,11 +649,12 @@ func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node {
// transformclosure already did all preparation work. // transformclosure already did all preparation work.
// Prepend captured variables to argument list. // Prepend captured variables to argument list.
n.PtrList().Prepend(n.Left().Func().ClosureEnter.Slice()...) clo := n.Left().(*ir.ClosureExpr)
n.Left().Func().ClosureEnter.Set(nil) n.PtrList().Prepend(clo.Func().ClosureEnter.Slice()...)
clo.Func().ClosureEnter.Set(nil)
// Replace OCLOSURE with ONAME/PFUNC. // Replace OCLOSURE with ONAME/PFUNC.
n.SetLeft(n.Left().Func().Nname) n.SetLeft(clo.Func().Nname)
// Update type of OCALLFUNC node. // Update type of OCALLFUNC node.
// Output arguments had not changed, but their offsets could. // Output arguments had not changed, but their offsets could.

View file

@ -1189,6 +1189,7 @@ func dumpNode(w io.Writer, n Node, depth int) {
case ODCLFUNC: case ODCLFUNC:
// Func has many fields we don't want to print. // Func has many fields we don't want to print.
// Bypass reflection and just print what we want. // Bypass reflection and just print what we want.
n := n.(*Func)
fmt.Fprintf(w, "%+v", n.Op()) fmt.Fprintf(w, "%+v", n.Op())
dumpNodeHeader(w, n) dumpNodeHeader(w, n)
fn := n.Func() fn := n.Func()

View file

@ -213,10 +213,21 @@ func (f *Func) SetWBPos(pos src.XPos) {
// funcname returns the name (without the package) of the function n. // funcname returns the name (without the package) of the function n.
func FuncName(n Node) string { func FuncName(n Node) string {
if n == nil || n.Func() == nil || n.Func().Nname == nil { var f *Func
switch n := n.(type) {
case *Func:
f = n
case *Name:
f = n.Func()
case *CallPartExpr:
f = n.Func()
case *ClosureExpr:
f = n.Func()
}
if f == nil || f.Nname == nil {
return "<nil>" return "<nil>"
} }
return n.Func().Nname.Sym().Name return f.Nname.Sym().Name
} }
// pkgFuncName returns the name of the function referenced by n, with package prepended. // pkgFuncName returns the name of the function referenced by n, with package prepended.
@ -231,10 +242,19 @@ func PkgFuncName(n Node) string {
if n.Op() == ONAME { if n.Op() == ONAME {
s = n.Sym() s = n.Sym()
} else { } else {
if n.Func() == nil || n.Func().Nname == nil { var f *Func
switch n := n.(type) {
case *CallPartExpr:
f = n.Func()
case *ClosureExpr:
f = n.Func()
case *Func:
f = n
}
if f == nil || f.Nname == nil {
return "<nil>" return "<nil>"
} }
s = n.Func().Nname.Sym() s = f.Nname.Sym()
} }
pkg := s.Pkg pkg := s.Pkg