aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-06-22 18:10:59 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-06-23 04:03:38 +0000
commitc4e0c652fbf3b17cc89f72c6569fe255fe5e1047 (patch)
treeff545984e43e0e1f95639489e9a05bde0dca6274 /src
parent62095c66e042024fc631a3e9514b637ae4b5ae10 (diff)
downloadgo-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')
-rw-r--r--src/cmd/compile/internal/ir/name.go47
-rw-r--r--src/cmd/compile/internal/noder/reader.go13
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)