]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.unified] cmd/compile: special case f(g()) calls in Unified IR
authorMatthew Dempsky <mdempsky@google.com>
Tue, 21 Jun 2022 11:41:38 +0000 (04:41 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 23 Jun 2022 21:53:38 +0000 (21:53 +0000)
For f(g()) calls where g() is multi-valued, we may need to insert
implicit conversions to convert g()'s result values to f()'s parameter
types. This CL refactors code slightly so this will be easier to
handle.

Change-Id: I3a432220dcb62daecf9a66030e8fa1f097e95f95
Reviewed-on: https://go-review.googlesource.com/c/go/+/413362
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/noder/reader.go
src/cmd/compile/internal/noder/writer.go

index aa2cccf86ba0c186bdbb5b1d93ef625319a9f8f4..bed56d1be7013f6e861552b291870c40e4507bf6 100644 (file)
@@ -1735,8 +1735,15 @@ func (r *reader) expr() (res ir.Node) {
                        fun = typecheck.Callee(ir.NewSelectorExpr(pos, ir.OXDOT, fun, sym))
                }
                pos := r.pos()
-               args := r.exprs()
-               dots := r.Bool()
+               var args ir.Nodes
+               var dots bool
+               if r.Bool() { // f(g())
+                       call := r.expr()
+                       args = []ir.Node{call}
+               } else {
+                       args = r.exprs()
+                       dots = r.Bool()
+               }
                n := typecheck.Call(pos, fun, args, dots)
                switch n.Op() {
                case ir.OAPPEND:
index 8ef63a0085626e0d9673147534bf27f5e9a12ff3..7bbd3abc5d31939ff8f2a157c13ee63983d2926f 100644 (file)
@@ -1505,8 +1505,14 @@ func (w *writer) expr(expr syntax.Expr) {
                w.Code(exprCall)
                writeFunExpr()
                w.pos(expr)
-               w.exprs(expr.ArgList)
-               w.Bool(expr.HasDots)
+               if w.Bool(len(expr.ArgList) == 1 && isMultiValueExpr(w.p.info, expr.ArgList[0])) {
+                       // f(g()) call
+                       assert(!expr.HasDots)
+                       w.expr(expr.ArgList[0])
+               } else {
+                       w.exprs(expr.ArgList)
+                       w.Bool(expr.HasDots)
+               }
        }
 }
 
@@ -1999,6 +2005,19 @@ func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
        return false
 }
 
+// isMultiValueExpr reports whether expr is a function call expression
+// that yields multiple values.
+func isMultiValueExpr(info *types2.Info, expr syntax.Expr) bool {
+       tv, ok := info.Types[expr]
+       assert(ok)
+       assert(tv.IsValue())
+       if tuple, ok := tv.Type.(*types2.Tuple); ok {
+               assert(tuple.Len() > 1)
+               return true
+       }
+       return false
+}
+
 // recvBase returns the base type for the given receiver parameter.
 func recvBase(recv *types2.Var) *types2.Named {
        typ := recv.Type()