mirror of
https://github.com/golang/go
synced 2024-11-26 02:07:57 -07: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() {
|
||||
inlMap[fn] = false
|
||||
}()
|
||||
|
||||
typecheck.FixVariadicCall(n)
|
||||
|
||||
if base.Debug.TypecheckInl == 0 {
|
||||
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...)
|
||||
|
||||
// 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 {
|
||||
as.Lhs.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.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 {
|
||||
ninit.Append(typecheck.Stmt(as))
|
||||
}
|
||||
|
||||
if vas != nil {
|
||||
ninit.Append(typecheck.Stmt(vas))
|
||||
}
|
||||
|
||||
if !delayretvars {
|
||||
// Zero the return parameters.
|
||||
for _, n := range retvars {
|
||||
@ -1078,18 +1047,6 @@ func retvar(t *types.Field, i int) *ir.Name {
|
||||
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
|
||||
// function call.
|
||||
type inlsubst struct {
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
|
||||
"fmt"
|
||||
"go/constant"
|
||||
@ -15,21 +16,21 @@ import (
|
||||
)
|
||||
|
||||
// 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
|
||||
if len(args) == 0 {
|
||||
n = NodNil()
|
||||
n = ir.NewNilExpr(pos)
|
||||
n.SetType(typ)
|
||||
} else {
|
||||
lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil)
|
||||
lit.List.Append(args...)
|
||||
args = append([]ir.Node(nil), args...)
|
||||
lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), args)
|
||||
lit.SetImplicit(true)
|
||||
n = lit
|
||||
}
|
||||
|
||||
n = Expr(n)
|
||||
if n.Type() == nil {
|
||||
base.Fatalf("mkdotargslice: typecheck failed")
|
||||
base.FatalfAt(pos, "mkdotargslice: typecheck failed")
|
||||
}
|
||||
return n
|
||||
}
|
||||
@ -47,7 +48,7 @@ func FixVariadicCall(call *ir.CallExpr) {
|
||||
|
||||
args := call.Args
|
||||
extra := args[vi:]
|
||||
slice := MakeDotArgs(vt, extra)
|
||||
slice := MakeDotArgs(call.Pos(), vt, extra)
|
||||
for i := range extra {
|
||||
extra[i] = nil // allow GC
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ func walkCheckPtrArithmetic(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
|
||||
|
||||
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)
|
||||
|
||||
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"
|
||||
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"
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user