[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.
// TODO: This creation of the named function should probably really be done in a
// separate pass from type-checking.
func typecheckclosure(clo ir.Node, top int) {
func typecheckclosure(clo *ir.ClosureExpr, top int) {
fn := clo.Func()
// Set current associated iota value, so iota can be used inside
// function in ConstSpec, see issue #22344
@ -327,13 +327,13 @@ func transformclosure(fn *ir.Func) {
// hasemptycvars reports whether closure clo has an
// empty list of captured vars.
func hasemptycvars(clo ir.Node) bool {
func hasemptycvars(clo *ir.ClosureExpr) bool {
return len(clo.Func().ClosureVars) == 0
}
// closuredebugruntimecheck applies boilerplate checks for debug flags
// and compiling runtime
func closuredebugruntimecheck(clo ir.Node) {
func closuredebugruntimecheck(clo *ir.ClosureExpr) {
if base.Debug.Closure > 0 {
if clo.Esc() == EscHeap {
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
// 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.
func closureType(clo ir.Node) *types.Type {
func closureType(clo *ir.ClosureExpr) *types.Type {
// Create closure in the form of a composite literal.
// supposing the closure captures an int i and a string s
// and has one float64 argument and no results,

View File

@ -892,6 +892,7 @@ func (c *nowritebarrierrecChecker) findExtraCalls(nn ir.Node) {
case ir.ONAME:
callee = arg.Name().Defn.(*ir.Func)
case ir.OCLOSURE:
arg := arg.(*ir.ClosureExpr)
callee = arg.Func()
default:
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:
n := n.(*ir.ClosureExpr)
k = e.spill(k, n)
// 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:
fn = v.(*ir.Name)
case v.Op() == ir.OCLOSURE:
fn = v.Func().Nname
fn = v.(*ir.ClosureExpr).Func().Nname
}
case ir.OCALLMETH:
fn = methodExprName(call.Left())
@ -1883,7 +1884,7 @@ func heapAllocReason(n ir.Node) string {
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"
}
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())
}
func (r *importReader) funcExt(n ir.Node) {
func (r *importReader) funcExt(n *ir.Name) {
r.linkname(n.Sym())
r.symIdx(n.Sym())
@ -654,7 +654,7 @@ func (r *importReader) methExt(m *types.Field) {
if r.bool() {
m.SetNointerface(true)
}
r.funcExt(ir.AsNode(m.Nname))
r.funcExt(m.Nname.(*ir.Name))
}
func (r *importReader) linkname(s *types.Sym) {

View File

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

View File

@ -237,7 +237,7 @@ func caninl(fn *ir.Func) {
n.Func().Inl = &ir.Inline{
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()),
}
@ -677,6 +677,7 @@ func inlCallee(fn ir.Node) *ir.Func {
return fn.Func()
}
case ir.OCLOSURE:
fn := fn.(*ir.ClosureExpr)
c := fn.Func()
caninl(c)
return c

View File

@ -270,9 +270,12 @@ func Main(archInit func(*Arch)) {
// before walk reaches a call of a closure.
timings.Start("fe", "xclosures")
for _, n := range Target.Decls {
if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil {
Curfn = n.(*ir.Func)
transformclosure(Curfn)
if n.Op() == ir.ODCLFUNC {
n := n.(*ir.Func)
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.nodeID = make(map[*ir.Func]uint32)
for _, n := range list {
if n.Op() == ir.ODCLFUNC && !n.Func().IsHiddenClosure() {
v.visit(n.(*ir.Func))
if n.Op() == ir.ODCLFUNC {
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:
n := n.(*ir.ClosureExpr)
if m := v.visit(n.Func()); m < min {
min = m
}

View File

@ -28,7 +28,7 @@ func findScope(marks []ir.Mark, pos src.XPos) ir.ScopeID {
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.
dwarfScopes := make([]dwarf.Scope, 1+len(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
case ir.OCLOSURE:
r := r.(*ir.ClosureExpr)
if hasemptycvars(r) {
if base.Debug.Closure > 0 {
base.WarnfAt(r.Pos(), "closure converted to global")

View File

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

View File

@ -649,11 +649,12 @@ func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node {
// transformclosure already did all preparation work.
// Prepend captured variables to argument list.
n.PtrList().Prepend(n.Left().Func().ClosureEnter.Slice()...)
n.Left().Func().ClosureEnter.Set(nil)
clo := n.Left().(*ir.ClosureExpr)
n.PtrList().Prepend(clo.Func().ClosureEnter.Slice()...)
clo.Func().ClosureEnter.Set(nil)
// Replace OCLOSURE with ONAME/PFUNC.
n.SetLeft(n.Left().Func().Nname)
n.SetLeft(clo.Func().Nname)
// Update type of OCALLFUNC node.
// 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:
// Func has many fields we don't want to print.
// Bypass reflection and just print what we want.
n := n.(*Func)
fmt.Fprintf(w, "%+v", n.Op())
dumpNodeHeader(w, n)
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.
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 n.Func().Nname.Sym().Name
return f.Nname.Sym().Name
}
// 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 {
s = n.Sym()
} 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>"
}
s = n.Func().Nname.Sym()
s = f.Nname.Sym()
}
pkg := s.Pkg