1
0
mirror of https://github.com/golang/go synced 2024-11-19 03:24:40 -07:00

cmd/compile/internal/ir: mark Addrtaken in NewAddrExpr

This CL changes NewAddrExpr to require its operand to always be
typechecked, so it can return an appropriately typechecked node and
mark Addrtaken as appropriate in the process.

Change-Id: I97c1f29305a9abfda35c42a43561c4c15fb5b52e
Reviewed-on: https://go-review.googlesource.com/c/go/+/522879
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2023-08-24 17:21:58 -07:00 committed by Gopher Robot
parent b036d7e17f
commit 611c3af30d
5 changed files with 19 additions and 103 deletions

View File

@ -211,17 +211,6 @@ func Main(archInit func(*ssagen.ArchInfo)) {
// Apply coverage fixups, if applicable. // Apply coverage fixups, if applicable.
coverage.Fixup() coverage.Fixup()
// Compute Addrtaken for names.
// We need to wait until typechecking is done so that when we see &x[i]
// we know that x has its address taken if x is an array, but not if x is a slice.
// We compute Addrtaken in bulk here.
// After this phase, we maintain Addrtaken incrementally.
if typecheck.DirtyAddrtaken {
typecheck.ComputeAddrtaken(typecheck.Target.Funcs)
typecheck.DirtyAddrtaken = false
}
typecheck.IncrementalAddrtaken = true
// Read profile file and build profile-graph and weighted-call-graph. // Read profile file and build profile-graph and weighted-call-graph.
base.Timer.Start("fe", "pgo-load-profile") base.Timer.Start("fe", "pgo-load-profile")
var profile *pgo.Profile var profile *pgo.Profile

View File

@ -78,9 +78,26 @@ type AddrExpr struct {
} }
func NewAddrExpr(pos src.XPos, x Node) *AddrExpr { func NewAddrExpr(pos src.XPos, x Node) *AddrExpr {
if x == nil || x.Typecheck() != 1 {
base.FatalfAt(pos, "missed typecheck: %L", x)
}
n := &AddrExpr{X: x} n := &AddrExpr{X: x}
n.op = OADDR
n.pos = pos n.pos = pos
switch x.Op() {
case OARRAYLIT, OMAPLIT, OSLICELIT, OSTRUCTLIT:
n.op = OPTRLIT
default:
n.op = OADDR
if r, ok := OuterValue(x).(*Name); ok && r.Op() == ONAME {
r.SetAddrtaken(true)
}
}
n.SetType(types.NewPtr(x.Type()))
n.SetTypecheck(1)
return n return n
} }

View File

@ -16,38 +16,6 @@ import (
"cmd/internal/src" "cmd/internal/src"
) )
// tcAddr typechecks an OADDR node.
func tcAddr(n *ir.AddrExpr) ir.Node {
n.X = Expr(n.X)
if n.X.Type() == nil {
n.SetType(nil)
return n
}
switch n.X.Op() {
case ir.OARRAYLIT, ir.OMAPLIT, ir.OSLICELIT, ir.OSTRUCTLIT:
n.SetOp(ir.OPTRLIT)
default:
checklvalue(n.X, "take the address of")
r := ir.OuterValue(n.X)
if r.Op() == ir.ONAME {
r := r.(*ir.Name)
if ir.Orig(r) != r {
base.Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean?
}
}
n.X = DefaultLit(n.X, nil)
if n.X.Type() == nil {
n.SetType(nil)
return n
}
}
n.SetType(types.NewPtr(n.X.Type()))
return n
}
func tcShift(n, l, r ir.Node) (ir.Node, ir.Node, *types.Type) { func tcShift(n, l, r ir.Node) (ir.Node, ir.Node, *types.Type) {
if l.Type() == nil || r.Type() == nil { if l.Type() == nil || r.Type() == nil {
return l, r, nil return l, r, nil

View File

@ -51,61 +51,7 @@ func NodAddr(n ir.Node) *ir.AddrExpr {
// NodAddrAt returns a node representing &n at position pos. // NodAddrAt returns a node representing &n at position pos.
func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr { func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr {
n = markAddrOf(n) return ir.NewAddrExpr(pos, Expr(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, and not loading the inlined body.
// 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().SetAddrtaken(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(funcs []*ir.Func) {
var doVisit func(n ir.Node)
doVisit = func(n ir.Node) {
if n.Op() == ir.OADDR {
if x := ir.OuterValue(n.(*ir.AddrExpr).X); x.Op() == ir.ONAME {
x.Name().SetAddrtaken(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().SetAddrtaken(true)
}
}
}
if n.Op() == ir.OCLOSURE {
ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doVisit)
}
}
for _, fn := range funcs {
ir.Visit(fn, doVisit)
}
} }
// LinksymAddr returns a new expression that evaluates to the address // LinksymAddr returns a new expression that evaluates to the address

View File

@ -346,10 +346,6 @@ func typecheck1(n ir.Node, top int) ir.Node {
return tcUnaryArith(n) return tcUnaryArith(n)
// exprs // exprs
case ir.OADDR:
n := n.(*ir.AddrExpr)
return tcAddr(n)
case ir.OCOMPLIT: case ir.OCOMPLIT:
return tcCompLit(n.(*ir.CompLitExpr)) return tcCompLit(n.(*ir.CompLitExpr))