mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[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:
parent
51ba53f5c2
commit
280e7fd1ee
14 changed files with 63 additions and 25 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue