diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-06-22 18:10:59 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-06-23 04:03:38 +0000 |
commit | c4e0c652fbf3b17cc89f72c6569fe255fe5e1047 (patch) | |
tree | ff545984e43e0e1f95639489e9a05bde0dca6274 /src/cmd/compile | |
parent | 62095c66e042024fc631a3e9514b637ae4b5ae10 (diff) | |
download | go-c4e0c652fbf3b17cc89f72c6569fe255fe5e1047.tar.gz go-c4e0c652fbf3b17cc89f72c6569fe255fe5e1047.zip |
[dev.typeparams] cmd/compile: refactor CaptureName
CaptureName currently does a few things: checks if a variable needs to
be captured at all; checks if the variable has already been captured;
and creates and saves a new variable. This full suite of functionality
is useful for noder and irgen, but unified IR and other backend code
only has a need for the last feature.
This CL refactors CaptureName a little bit and extracts out
NewClosureVar as a function usable for callers that don't need the
extra features of CaptureName.
Change-Id: I8a67c6375e44babe53344bf78e335535c57f9607
Reviewed-on: https://go-review.googlesource.com/c/go/+/330193
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile')
-rw-r--r-- | src/cmd/compile/internal/ir/name.go | 47 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 13 |
2 files changed, 33 insertions, 27 deletions
diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index b6c68bc5e0..ff9784df1b 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -358,39 +358,52 @@ func (n *Name) Byval() bool { return n.Canonical().flags&nameByval != 0 } +// NewClosureVar creates a new closure variable for fn to refer to +// outer variable n. +func NewClosureVar(pos src.XPos, fn *Func, n *Name) *Name { + c := NewNameAt(pos, n.Sym()) + c.Curfn = fn + c.Class = PAUTOHEAP + c.SetIsClosureVar(true) + c.Defn = n.Canonical() + c.Outer = n + + fn.ClosureVars = append(fn.ClosureVars, c) + + return c +} + // CaptureName returns a Name suitable for referring to n from within function // fn or from the package block if fn is nil. If n is a free variable declared -// within a function that encloses fn, then CaptureName returns a closure -// variable that refers to n and adds it to fn.ClosureVars. Otherwise, it simply -// returns n. +// within a function that encloses fn, then CaptureName returns the closure +// variable that refers to n within fn, creating it if necessary. +// Otherwise, it simply returns n. func CaptureName(pos src.XPos, fn *Func, n *Name) *Name { - if n.IsClosureVar() { - base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) - } - if n.Op() != ONAME || n.Curfn == nil || n.Curfn == fn { + if n.Op() != ONAME || n.Curfn == nil { return n // okay to use directly } - if fn == nil { - base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn) + if n.IsClosureVar() { + base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) } c := n.Innermost - if c != nil && c.Curfn == fn { + if c == nil { + c = n + } + if c.Curfn == fn { return c } + if fn == nil { + base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn) + } + // Do not have a closure var for the active closure yet; make one. - c = NewNameAt(pos, n.Sym()) - c.Curfn = fn - c.Class = PAUTOHEAP - c.SetIsClosureVar(true) - c.Defn = n + c = NewClosureVar(pos, fn, c) // Link into list of active closure variables. // Popped from list in FinishCaptureNames. - c.Outer = n.Innermost n.Innermost = c - fn.ClosureVars = append(fn.ClosureVars, c) return c } diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 4fc9e7a777..b106e89892 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1558,20 +1558,13 @@ func (r *reader) funcLit() ir.Node { fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2) } - fn.ClosureVars = make([]*ir.Name, r.len()) - for i := range fn.ClosureVars { + fn.ClosureVars = make([]*ir.Name, 0, r.len()) + for len(fn.ClosureVars) < cap(fn.ClosureVars) { pos := r.pos() outer := r.useLocal() - cv := ir.NewNameAt(pos, outer.Sym()) + cv := ir.NewClosureVar(pos, fn, outer) r.setType(cv, outer.Type()) - cv.Curfn = fn - cv.Class = ir.PAUTOHEAP - cv.SetIsClosureVar(true) - cv.Defn = outer.Canonical() - cv.Outer = outer - - fn.ClosureVars[i] = cv } r.addBody(fn) |