diff options
author | Keith Randall <khr@golang.org> | 2020-11-28 16:01:58 -0800 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2020-12-29 18:04:10 +0000 |
commit | 0523d525ae0dea229cffc5634caddd0acbc066af (patch) | |
tree | ad08e8b89b02662043d39e04ba410a601595f386 /src/cmd/compile/internal/typecheck/subr.go | |
parent | 9ea272e5ec5dd5eadd59d54c08377d5d9527a51b (diff) | |
download | go-0523d525ae0dea229cffc5634caddd0acbc066af.tar.gz go-0523d525ae0dea229cffc5634caddd0acbc066af.zip |
[dev.regabi] cmd/compile: separate out address taken computation from typechecker
This CL computes a second parallel addrtaken bit that we check
against the old way of doing it. A subsequent CL will rip out the
typechecker code and just use the new way.
Change-Id: I62b7342c44f694144844695386f80088bbd40bf4
Reviewed-on: https://go-review.googlesource.com/c/go/+/275695
Trust: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
Diffstat (limited to 'src/cmd/compile/internal/typecheck/subr.go')
-rw-r--r-- | src/cmd/compile/internal/typecheck/subr.go | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 178eba4484..8d31fea9ec 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -67,9 +67,57 @@ func NodAddr(n ir.Node) *ir.AddrExpr { // nodAddrPos returns a node representing &n at position pos. func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr { + n = markAddrOf(n) return ir.NewAddrExpr(pos, n) } +func markAddrOf(n ir.Node) ir.Node { + if incrementalAddrtaken { + // We can only do incremental addrtaken computation when it is ok + // to typecheck the argument of the OADDR. That's only safe after the + // main typecheck has completed. + // The argument to OADDR needs to be typechecked because &x[i] takes + // the address of x if x is an array, but not if x is a slice. + // Note: outervalue doesn't work correctly until n is typechecked. + n = typecheck(n, ctxExpr) + if x := ir.OuterValue(n); x.Op() == ir.ONAME { + x.Name().SetAddrtaken2(true) + } + } else { + // Remember that we built an OADDR without computing the Addrtaken bit for + // its argument. We'll do that later in bulk using computeAddrtaken. + dirtyAddrtaken = true + } + return n +} + +// If incrementalAddrtaken is false, we do not compute Addrtaken for an OADDR Node +// when it is built. The Addrtaken bits are set in bulk by computeAddrtaken. +// If incrementalAddrtaken is true, then when an OADDR Node is built the Addrtaken +// field of its argument is updated immediately. +var incrementalAddrtaken = false + +// If dirtyAddrtaken is true, then there are OADDR whose corresponding arguments +// have not yet been marked as Addrtaken. +var dirtyAddrtaken = false + +func computeAddrtaken(top []ir.Node) { + for _, n := range top { + ir.Visit(n, func(n ir.Node) { + if n.Op() == ir.OADDR { + if x := ir.OuterValue(n.(*ir.AddrExpr).X); x.Op() == ir.ONAME { + x.Name().SetAddrtaken2(true) + if x.Name().IsClosureVar() { + // Mark the original variable as Addrtaken so that capturevars + // knows not to pass it by value. + x.Name().Defn.Name().SetAddrtaken2(true) + } + } + } + }) + } +} + func NodNil() ir.Node { n := ir.NewNilExpr(base.Pos) n.SetType(types.Types[types.TNIL]) |