]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: simplify inlining variadic calls
authorMatthew Dempsky <mdempsky@google.com>
Wed, 26 May 2021 03:14:33 +0000 (20:14 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 26 May 2021 23:50:45 +0000 (23:50 +0000)
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>
src/cmd/compile/internal/inline/inl.go
src/cmd/compile/internal/typecheck/func.go
src/cmd/compile/internal/walk/convert.go
test/fixedbugs/issue30898.go
test/inline_variadic.go

index 263e0b310b26a335486591e6c63fad03a490f620..00f8447f059631b997923816f445ee696abffad5 100644 (file)
@@ -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
-               }
+               as.Lhs.Append(inlParam(param, as, inlvars))
        }
 
        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 {
index f381e1dbdc49db47c600280f4e376e24af10cc94..760b8868ab72e87583eed29bbe0dcda5e3d8e162 100644 (file)
@@ -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
        }
index 26e17a126f22151a542fecf9026002846baa82ca..5297332f6b06ff4218bf38d58b2a44a98d11419b 100644 (file)
@@ -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))
index b6376d3f9e7a7fe0ae223db0c869bd9a0dc6c9fa..c7f6f2d3712b3cf507cbc8d1338a4604d99e5c47 100644 (file)
@@ -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"
 }
index 687048a1922d55ca42ac1c334bd1380978e4d499..49483d77f79934b9f4011da0705daba3faeb2a7b 100644 (file)
@@ -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
 }