mirror of https://github.com/golang/go.git
[dev.unified] cmd/compile: special case f(g()) calls in Unified IR
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>
This commit is contained in:
parent
61ae2b734c
commit
20e1d5ac8c
|
|
@ -1735,8 +1735,15 @@ func (r *reader) expr() (res ir.Node) {
|
||||||
fun = typecheck.Callee(ir.NewSelectorExpr(pos, ir.OXDOT, fun, sym))
|
fun = typecheck.Callee(ir.NewSelectorExpr(pos, ir.OXDOT, fun, sym))
|
||||||
}
|
}
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
args := r.exprs()
|
var args ir.Nodes
|
||||||
dots := r.Bool()
|
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)
|
n := typecheck.Call(pos, fun, args, dots)
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ir.OAPPEND:
|
case ir.OAPPEND:
|
||||||
|
|
|
||||||
|
|
@ -1505,8 +1505,14 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
w.Code(exprCall)
|
w.Code(exprCall)
|
||||||
writeFunExpr()
|
writeFunExpr()
|
||||||
w.pos(expr)
|
w.pos(expr)
|
||||||
w.exprs(expr.ArgList)
|
if w.Bool(len(expr.ArgList) == 1 && isMultiValueExpr(w.p.info, expr.ArgList[0])) {
|
||||||
w.Bool(expr.HasDots)
|
// 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
|
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.
|
// recvBase returns the base type for the given receiver parameter.
|
||||||
func recvBase(recv *types2.Var) *types2.Named {
|
func recvBase(recv *types2.Var) *types2.Named {
|
||||||
typ := recv.Type()
|
typ := recv.Type()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue