mirror of
https://github.com/golang/go
synced 2024-09-23 11:20:17 -06:00
cmd/compile: set n.Name.Defn for inlined parameters
Normally, when variables are declared and initialized using ":=", we set the variable's n.Name.Defn to point to the initialization assignment node (i.e., OAS or OAS2). Further, some frontend optimizations look for variables that are initialized but never reassigned. However, when inl.go inlines calls, it was declaring the inlined variables, and then separately assigning to them. This CL changes inl.go tweaks the AST to fit the combined declaration+initialization pattern. This isn't terribly useful by itself, but it allows further followup optimizations. Updates #41474. Change-Id: I62a9752c60414305679e0ed15a6563baa0224efa Reviewed-on: https://go-review.googlesource.com/c/go/+/256457 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
8773d14164
commit
cced777026
@ -831,16 +831,19 @@ func (v *reassignVisitor) visitList(l Nodes) *Node {
|
||||
return nil
|
||||
}
|
||||
|
||||
func tinlvar(t *types.Field, inlvars map[*Node]*Node) *Node {
|
||||
if n := asNode(t.Nname); n != nil && !n.isBlank() {
|
||||
inlvar := inlvars[n]
|
||||
if inlvar == nil {
|
||||
Fatalf("missing inlvar for %v\n", n)
|
||||
}
|
||||
return inlvar
|
||||
func inlParam(t *types.Field, as *Node, inlvars map[*Node]*Node) *Node {
|
||||
n := asNode(t.Nname)
|
||||
if n == nil || n.isBlank() {
|
||||
return nblank
|
||||
}
|
||||
|
||||
return typecheck(nblank, ctxExpr|ctxAssign)
|
||||
inlvar := inlvars[n]
|
||||
if inlvar == nil {
|
||||
Fatalf("missing inlvar for %v", n)
|
||||
}
|
||||
as.Ninit.Append(nod(ODCL, inlvar, nil))
|
||||
inlvar.Name.Defn = as
|
||||
return inlvar
|
||||
}
|
||||
|
||||
var inlgen int
|
||||
@ -970,14 +973,15 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||
continue
|
||||
}
|
||||
if ln.isParamStackCopy() { // ignore the on-stack copy of a parameter that moved to the heap
|
||||
continue
|
||||
}
|
||||
inlvars[ln] = typecheck(inlvar(ln), ctxExpr)
|
||||
if ln.Class() == PPARAM || ln.Name.Param.Stackcopy != nil && ln.Name.Param.Stackcopy.Class() == PPARAM {
|
||||
ninit.Append(nod(ODCL, inlvars[ln], nil))
|
||||
// TODO(mdempsky): Remove once I'm confident
|
||||
// this never actually happens. We currently
|
||||
// perform inlining before escape analysis, so
|
||||
// nothing should have moved to the heap yet.
|
||||
Fatalf("impossible: %v", ln)
|
||||
}
|
||||
inlf := typecheck(inlvar(ln), ctxExpr)
|
||||
inlvars[ln] = inlf
|
||||
if genDwarfInline > 0 {
|
||||
inlf := inlvars[ln]
|
||||
if ln.Class() == PPARAM {
|
||||
inlf.Name.SetInlFormal(true)
|
||||
} else {
|
||||
@ -1019,56 +1023,42 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||
|
||||
// Assign arguments to the parameters' temp names.
|
||||
as := nod(OAS2, nil, nil)
|
||||
as.Rlist.Set(n.List.Slice())
|
||||
as.SetColas(true)
|
||||
if n.Op == OCALLMETH {
|
||||
if n.Left.Left == nil {
|
||||
Fatalf("method call without receiver: %+v", n)
|
||||
}
|
||||
as.Rlist.Append(n.Left.Left)
|
||||
}
|
||||
as.Rlist.Append(n.List.Slice()...)
|
||||
|
||||
// For non-dotted calls to variadic functions, we assign the
|
||||
// variadic parameter's temp name separately.
|
||||
var vas *Node
|
||||
|
||||
if fn.IsMethod() {
|
||||
rcv := fn.Type.Recv()
|
||||
|
||||
if n.Left.Op == ODOTMETH {
|
||||
// For x.M(...), assign x directly to the
|
||||
// receiver parameter.
|
||||
if n.Left.Left == nil {
|
||||
Fatalf("method call without receiver: %+v", n)
|
||||
}
|
||||
ras := nod(OAS, tinlvar(rcv, inlvars), n.Left.Left)
|
||||
ras = typecheck(ras, ctxStmt)
|
||||
ninit.Append(ras)
|
||||
} else {
|
||||
// For T.M(...), add the receiver parameter to
|
||||
// as.List, so it's assigned by the normal
|
||||
// arguments.
|
||||
if as.Rlist.Len() == 0 {
|
||||
Fatalf("non-method call to method without first arg: %+v", n)
|
||||
}
|
||||
as.List.Append(tinlvar(rcv, inlvars))
|
||||
}
|
||||
if recv := fn.Type.Recv(); recv != nil {
|
||||
as.List.Append(inlParam(recv, as, inlvars))
|
||||
}
|
||||
|
||||
for _, param := range fn.Type.Params().Fields().Slice() {
|
||||
// For ordinary parameters or variadic parameters in
|
||||
// dotted calls, just add the variable to the
|
||||
// assignment list, and we're done.
|
||||
if !param.IsDDD() || n.IsDDD() {
|
||||
as.List.Append(tinlvar(param, inlvars))
|
||||
as.List.Append(inlParam(param, as, inlvars))
|
||||
continue
|
||||
}
|
||||
|
||||
// Otherwise, we need to collect the remaining values
|
||||
// to pass as a slice.
|
||||
|
||||
numvals := n.List.Len()
|
||||
|
||||
x := as.List.Len()
|
||||
for as.List.Len() < numvals {
|
||||
for as.List.Len() < as.Rlist.Len() {
|
||||
as.List.Append(argvar(param.Type, as.List.Len()))
|
||||
}
|
||||
varargs := as.List.Slice()[x:]
|
||||
|
||||
vas = nod(OAS, tinlvar(param, inlvars), nil)
|
||||
vas = nod(OAS, nil, nil)
|
||||
vas.Left = inlParam(param, vas, inlvars)
|
||||
if len(varargs) == 0 {
|
||||
vas.Right = nodnil()
|
||||
vas.Right.Type = param.Type
|
||||
|
@ -213,7 +213,7 @@ func s15a8(x *[15]int64) [15]int64 {
|
||||
want(t, slogged, `{"range":{"start":{"line":7,"character":13},"end":{"line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0",`+
|
||||
`"relatedInformation":[`+
|
||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y = z:"},`+
|
||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y = \u003cN\u003e (assign-pair)"},`+
|
||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y := z (assign-pair)"},`+
|
||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~r1 = y:"},`+
|
||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+
|
||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y.b (dot of pointer)"},`+
|
||||
|
Loading…
Reference in New Issue
Block a user