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>
// 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
// 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)
// 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,
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)
}
case ir.OCLOSURE:
+ n := n.(*ir.ClosureExpr)
k = e.spill(k, n)
// Link addresses of captured variables to closure.
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())
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 {
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())
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) {
}
case ir.OCLOSURE:
+ n := n.(*ir.ClosureExpr)
d.inspectList(n.Func().Body())
case ir.ODOTMETH, ir.OCALLPART:
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()),
}
return fn.Func()
}
case ir.OCLOSURE:
+ fn := fn.(*ir.ClosureExpr)
c := fn.Func()
caninl(c)
return c
// 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)
+ }
}
}
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)
+ }
}
}
}
}
}
case ir.OCLOSURE:
+ n := n.(*ir.ClosureExpr)
if m := v.visit(n.Func()); m < min {
min = m
}
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 {
break
case ir.OCLOSURE:
+ r := r.(*ir.ClosureExpr)
if hasemptycvars(r) {
if base.Debug.Closure > 0 {
base.WarnfAt(r.Pos(), "closure converted to global")
// 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
return n
case ir.OCLOSURE:
+ n := n.(*ir.ClosureExpr)
typecheckclosure(n, top)
if n.Type() == nil {
return n
// 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.
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()
// 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.
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