diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-01-11 15:58:19 -0800 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-01-12 02:46:27 +0000 |
commit | b4d2a0445b0ca54a159e0895e1a8b31d47411894 (patch) | |
tree | 2749d36d62ec3b0ea128e39766c49527cfc73978 /src/cmd/compile/internal/noder/noder.go | |
parent | f57f484053f276c6fb57047cf02fa043974d7b95 (diff) | |
download | go-b4d2a0445b0ca54a159e0895e1a8b31d47411894.tar.gz go-b4d2a0445b0ca54a159e0895e1a8b31d47411894.zip |
[dev.regabi] cmd/compile: refactor closure var setup/teardown
Creating closure vars is subtle and is also needed in both CL 281932
and CL 283112, so refactor out a common implementation that can be
used in all 3 places.
Passes toolstash -cmp.
Change-Id: Ib993eb90c895b52759bfbfbaad88921e391b0b4d
Reviewed-on: https://go-review.googlesource.com/c/go/+/283194
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
Trust: Dan Scales <danscales@google.com>
Trust: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder/noder.go')
-rw-r--r-- | src/cmd/compile/internal/noder/noder.go | 64 |
1 files changed, 3 insertions, 61 deletions
diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 76913c62a6..ec0debdbbd 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -1872,45 +1872,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { p.funcBody(fn, expr.Body) - // closure-specific variables are hanging off the - // ordinary ones in the symbol table; see oldname. - // unhook them. - // make the list of pointers for the closure call. - for _, v := range fn.ClosureVars { - // Unlink from v1; see comment in syntax.go type Param for these fields. - v1 := v.Defn - v1.Name().Innermost = v.Outer - - // If the closure usage of v is not dense, - // we need to make it dense; now that we're out - // of the function in which v appeared, - // look up v.Sym in the enclosing function - // and keep it around for use in the compiled code. - // - // That is, suppose we just finished parsing the innermost - // closure f4 in this code: - // - // func f() { - // v := 1 - // func() { // f2 - // use(v) - // func() { // f3 - // func() { // f4 - // use(v) - // }() - // }() - // }() - // } - // - // At this point v.Outer is f2's v; there is no f3's v. - // To construct the closure f4 from within f3, - // we need to use f3's v and in this case we need to create f3's v. - // We are now in the context of f3, so calling oldname(v.Sym) - // obtains f3's v, creating it if necessary (as it is in the example). - // - // capturevars will decide whether to use v directly or &v. - v.Outer = oldname(v.Sym()).(*ir.Name) - } + ir.FinishCaptureNames(base.Pos, ir.CurFunc, fn) return clo } @@ -1944,32 +1906,12 @@ func oldname(s *types.Sym) ir.Node { return ir.NewIdent(base.Pos, s) } - if ir.CurFunc != nil && n.Op() == ir.ONAME && n.Name().Curfn != nil && n.Name().Curfn != ir.CurFunc { - // Inner func is referring to var in outer func. - // + if n, ok := n.(*ir.Name); ok { // TODO(rsc): If there is an outer variable x and we // are parsing x := 5 inside the closure, until we get to // the := it looks like a reference to the outer x so we'll // make x a closure variable unnecessarily. - n := n.(*ir.Name) - c := n.Innermost - if c == nil || c.Curfn != ir.CurFunc { - // Do not have a closure var for the active closure yet; make one. - c = typecheck.NewName(s) - c.Class = ir.PAUTOHEAP - c.SetIsClosureVar(true) - c.Defn = n - - // Link into list of active closure variables. - // Popped from list in func funcLit. - c.Outer = n.Innermost - n.Innermost = c - - ir.CurFunc.ClosureVars = append(ir.CurFunc.ClosureVars, c) - } - - // return ref to closure var, not original - return c + return ir.CaptureName(base.Pos, ir.CurFunc, n) } return n |