mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
[dev.typeparams] cmd/compile: simplify inlining variadic calls
We already have and use FixVariadicCall to normalize non-dotted calls to variadic functions elsewhere in the compiler to simplify rewriting of function calls. This CL updates inl.go to use it too. A couple tests need to be updated to (correctly) expect diagnostics about "... argument" instead of a slice literal. This is because inl.go previously failed to set Implicit on the slice literal node. Change-Id: I76bd79b95ae1f16e3b26ff7e9e1c468f538fd1f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/323009 Trust: Matthew Dempsky <mdempsky@google.com> Trust: Dan Scales <danscales@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
parent
e99e9a6e01
commit
6da1661371
|
@ -793,6 +793,9 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
|
||||||
defer func() {
|
defer func() {
|
||||||
inlMap[fn] = false
|
inlMap[fn] = false
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
typecheck.FixVariadicCall(n)
|
||||||
|
|
||||||
if base.Debug.TypecheckInl == 0 {
|
if base.Debug.TypecheckInl == 0 {
|
||||||
typecheck.ImportedBody(fn)
|
typecheck.ImportedBody(fn)
|
||||||
}
|
}
|
||||||
|
@ -914,51 +917,17 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
|
||||||
}
|
}
|
||||||
as.Rhs.Append(n.Args...)
|
as.Rhs.Append(n.Args...)
|
||||||
|
|
||||||
// For non-dotted calls to variadic functions, we assign the
|
|
||||||
// variadic parameter's temp name separately.
|
|
||||||
var vas *ir.AssignStmt
|
|
||||||
|
|
||||||
if recv := fn.Type().Recv(); recv != nil {
|
if recv := fn.Type().Recv(); recv != nil {
|
||||||
as.Lhs.Append(inlParam(recv, as, inlvars))
|
as.Lhs.Append(inlParam(recv, as, inlvars))
|
||||||
}
|
}
|
||||||
for _, param := range fn.Type().Params().Fields().Slice() {
|
for _, param := range fn.Type().Params().Fields().Slice() {
|
||||||
// For ordinary parameters or variadic parameters in
|
as.Lhs.Append(inlParam(param, as, inlvars))
|
||||||
// dotted calls, just add the variable to the
|
|
||||||
// assignment list, and we're done.
|
|
||||||
if !param.IsDDD() || n.IsDDD {
|
|
||||||
as.Lhs.Append(inlParam(param, as, inlvars))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we need to collect the remaining values
|
|
||||||
// to pass as a slice.
|
|
||||||
|
|
||||||
x := len(as.Lhs)
|
|
||||||
for len(as.Lhs) < len(as.Rhs) {
|
|
||||||
as.Lhs.Append(argvar(param.Type, len(as.Lhs)))
|
|
||||||
}
|
|
||||||
varargs := as.Lhs[x:]
|
|
||||||
|
|
||||||
vas = ir.NewAssignStmt(base.Pos, nil, nil)
|
|
||||||
vas.X = inlParam(param, vas, inlvars)
|
|
||||||
if len(varargs) == 0 {
|
|
||||||
vas.Y = typecheck.NodNil()
|
|
||||||
vas.Y.SetType(param.Type)
|
|
||||||
} else {
|
|
||||||
lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(param.Type), nil)
|
|
||||||
lit.List = varargs
|
|
||||||
vas.Y = lit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(as.Rhs) != 0 {
|
if len(as.Rhs) != 0 {
|
||||||
ninit.Append(typecheck.Stmt(as))
|
ninit.Append(typecheck.Stmt(as))
|
||||||
}
|
}
|
||||||
|
|
||||||
if vas != nil {
|
|
||||||
ninit.Append(typecheck.Stmt(vas))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !delayretvars {
|
if !delayretvars {
|
||||||
// Zero the return parameters.
|
// Zero the return parameters.
|
||||||
for _, n := range retvars {
|
for _, n := range retvars {
|
||||||
|
@ -1078,18 +1047,6 @@ func retvar(t *types.Field, i int) *ir.Name {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synthesize a variable to store the inlined function's arguments
|
|
||||||
// when they come from a multiple return call.
|
|
||||||
func argvar(t *types.Type, i int) ir.Node {
|
|
||||||
n := typecheck.NewName(typecheck.LookupNum("~arg", i))
|
|
||||||
n.SetType(t.Elem())
|
|
||||||
n.Class = ir.PAUTO
|
|
||||||
n.SetUsed(true)
|
|
||||||
n.Curfn = ir.CurFunc // the calling function, not the called one
|
|
||||||
ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, n)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// The inlsubst type implements the actual inlining of a single
|
// The inlsubst type implements the actual inlining of a single
|
||||||
// function call.
|
// function call.
|
||||||
type inlsubst struct {
|
type inlsubst struct {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
|
"cmd/internal/src"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
|
@ -15,21 +16,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// package all the arguments that match a ... T parameter into a []T.
|
// package all the arguments that match a ... T parameter into a []T.
|
||||||
func MakeDotArgs(typ *types.Type, args []ir.Node) ir.Node {
|
func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node {
|
||||||
var n ir.Node
|
var n ir.Node
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
n = NodNil()
|
n = ir.NewNilExpr(pos)
|
||||||
n.SetType(typ)
|
n.SetType(typ)
|
||||||
} else {
|
} else {
|
||||||
lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil)
|
args = append([]ir.Node(nil), args...)
|
||||||
lit.List.Append(args...)
|
lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), args)
|
||||||
lit.SetImplicit(true)
|
lit.SetImplicit(true)
|
||||||
n = lit
|
n = lit
|
||||||
}
|
}
|
||||||
|
|
||||||
n = Expr(n)
|
n = Expr(n)
|
||||||
if n.Type() == nil {
|
if n.Type() == nil {
|
||||||
base.Fatalf("mkdotargslice: typecheck failed")
|
base.FatalfAt(pos, "mkdotargslice: typecheck failed")
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
@ -47,7 +48,7 @@ func FixVariadicCall(call *ir.CallExpr) {
|
||||||
|
|
||||||
args := call.Args
|
args := call.Args
|
||||||
extra := args[vi:]
|
extra := args[vi:]
|
||||||
slice := MakeDotArgs(vt, extra)
|
slice := MakeDotArgs(call.Pos(), vt, extra)
|
||||||
for i := range extra {
|
for i := range extra {
|
||||||
extra[i] = nil // allow GC
|
extra[i] = nil // allow GC
|
||||||
}
|
}
|
||||||
|
|
|
@ -499,7 +499,7 @@ func walkCheckPtrArithmetic(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
|
||||||
|
|
||||||
cheap := cheapExpr(n, init)
|
cheap := cheapExpr(n, init)
|
||||||
|
|
||||||
slice := typecheck.MakeDotArgs(types.NewSlice(types.Types[types.TUNSAFEPTR]), originals)
|
slice := typecheck.MakeDotArgs(base.Pos, types.NewSlice(types.Types[types.TUNSAFEPTR]), originals)
|
||||||
slice.SetEsc(ir.EscNone)
|
slice.SetEsc(ir.EscNone)
|
||||||
|
|
||||||
init.Append(mkcall("checkptrArithmetic", nil, init, typecheck.ConvNop(cheap, types.Types[types.TUNSAFEPTR]), slice))
|
init.Append(mkcall("checkptrArithmetic", nil, init, typecheck.ConvNop(cheap, types.Types[types.TUNSAFEPTR]), slice))
|
||||||
|
|
|
@ -15,5 +15,5 @@ func debugf(format string, args ...interface{}) { // ERROR "can inline debugf" "
|
||||||
|
|
||||||
func bar() { // ERROR "can inline bar"
|
func bar() { // ERROR "can inline bar"
|
||||||
value := 10
|
value := 10
|
||||||
debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\[\]interface {}{...} does not escape"
|
debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\.\.\. argument does not escape"
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,6 @@ func head(xs ...string) string { // ERROR "can inline head" "leaking param: xs t
|
||||||
}
|
}
|
||||||
|
|
||||||
func f() string { // ERROR "can inline f"
|
func f() string { // ERROR "can inline f"
|
||||||
x := head("hello", "world") // ERROR "inlining call to head" "\[\]string{...} does not escape"
|
x := head("hello", "world") // ERROR "inlining call to head" "\.\.\. argument does not escape"
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue