mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00:00
[dev.typeparams] cmd/compile: escape analysis of method expression calls
This CL extends escape analysis to analyze function calls using method expressions the same as it would a normal method call. That is, it now analyzes "T.M(recv, args...)" the same as "recv.M(args...)". This is useful because it means the frontend can eventually stop supporting both function calls and method calls. We can simply desugar method calls into function calls, like we already do in the backend to simplify SSA construction. Change-Id: I9cd5ec0d534cbcd9860f0014c86e4ae416920c26 Reviewed-on: https://go-review.googlesource.com/c/go/+/330331 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
0a0e3a3dea
commit
eb691fdd62
|
@ -56,11 +56,15 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
|
||||||
var fn *ir.Name
|
var fn *ir.Name
|
||||||
switch call.Op() {
|
switch call.Op() {
|
||||||
case ir.OCALLFUNC:
|
case ir.OCALLFUNC:
|
||||||
switch v := ir.StaticValue(call.X); {
|
switch v := ir.StaticValue(call.X); v.Op() {
|
||||||
case v.Op() == ir.ONAME && v.(*ir.Name).Class == ir.PFUNC:
|
case ir.ONAME:
|
||||||
fn = v.(*ir.Name)
|
if v := v.(*ir.Name); v.Class == ir.PFUNC {
|
||||||
case v.Op() == ir.OCLOSURE:
|
fn = v
|
||||||
|
}
|
||||||
|
case ir.OCLOSURE:
|
||||||
fn = v.(*ir.ClosureExpr).Func.Nname
|
fn = v.(*ir.ClosureExpr).Func.Nname
|
||||||
|
case ir.OMETHEXPR:
|
||||||
|
fn = ir.MethodExprName(v)
|
||||||
}
|
}
|
||||||
case ir.OCALLMETH:
|
case ir.OCALLMETH:
|
||||||
fn = ir.MethodExprName(call.X)
|
fn = ir.MethodExprName(call.X)
|
||||||
|
@ -77,19 +81,30 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r := fntype.Recv(); r != nil {
|
var recvp *ir.Node
|
||||||
dot := call.X.(*ir.SelectorExpr)
|
if call.Op() == ir.OCALLFUNC {
|
||||||
argumentFunc(fn, e.tagHole(ks, fn, r), &dot.X)
|
|
||||||
} else {
|
|
||||||
// Evaluate callee function expression.
|
// Evaluate callee function expression.
|
||||||
//
|
//
|
||||||
// Note: We use argument and not argumentFunc, because call.X
|
// Note: We use argument and not argumentFunc, because while
|
||||||
// here may be an argument to runtime.{new,defer}proc, but it's
|
// call.X here may be an argument to runtime.{new,defer}proc,
|
||||||
// not an argument to fn itself.
|
// it's not an argument to fn itself.
|
||||||
argument(e.discardHole(), &call.X)
|
argument(e.discardHole(), &call.X)
|
||||||
|
} else {
|
||||||
|
recvp = &call.X.(*ir.SelectorExpr).X
|
||||||
}
|
}
|
||||||
|
|
||||||
args := call.Args
|
args := call.Args
|
||||||
|
if recv := fntype.Recv(); recv != nil {
|
||||||
|
if recvp == nil {
|
||||||
|
// Function call using method expression. Recevier argument is
|
||||||
|
// at the front of the regular arguments list.
|
||||||
|
recvp = &args[0]
|
||||||
|
args = args[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
argumentFunc(fn, e.tagHole(ks, fn, recv), recvp)
|
||||||
|
}
|
||||||
|
|
||||||
for i, param := range fntype.Params().FieldSlice() {
|
for i, param := range fntype.Params().FieldSlice() {
|
||||||
argumentFunc(fn, e.tagHole(ks, fn, param), &args[i])
|
argumentFunc(fn, e.tagHole(ks, fn, param), &args[i])
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,8 +180,7 @@ func _() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func fbad24305() {
|
func fbad24305() {
|
||||||
// BAD u should not be heap allocated
|
var u U
|
||||||
var u U // ERROR "moved to heap: u"
|
|
||||||
(*U).M(&u)
|
(*U).M(&u)
|
||||||
(*U).N(&u)
|
(*U).N(&u)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue