cmd/compile: apply FixVariadicCall and FixMethodCall during typecheck

To simplify backend analysis, we normalize variadic and method calls:
variadic calls are rewritten with an explicit slice argument, and
method calls are turned into function calls that pass the receiver
argument as the first parameter.

But because we've been supporting multiple frontends, this
normalization was scattered in various later passes. Now that we're
back to just one frontend, we can move the normalization forward into
typecheck (where most other IR normalization already happens).

Change-Id: Idd05ae231fc180ae3dd1664452414f6b6d578962
Reviewed-on: https://go-review.googlesource.com/c/go/+/463737
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Matthew Dempsky 2022-12-20 11:23:23 -08:00 committed by Gopher Robot
parent 4e3abee245
commit 7cf8593140
4 changed files with 13 additions and 4 deletions

View file

@ -45,8 +45,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
call := call.(*ir.CallExpr) call := call.(*ir.CallExpr)
typecheck.FixVariadicCall(call) typecheck.AssertFixedCall(call)
typecheck.FixMethodCall(call)
// Pick out the function callee, if statically known. // Pick out the function callee, if statically known.
// //

View file

@ -981,7 +981,7 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlCalls *[]*ir.Inlin
} }
} }
typecheck.FixVariadicCall(n) typecheck.AssertFixedCall(n)
inlIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), sym) inlIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), sym)

View file

@ -76,6 +76,15 @@ func FixMethodCall(call *ir.CallExpr) {
call.Args = args call.Args = args
} }
func AssertFixedCall(call *ir.CallExpr) {
if call.X.Type().IsVariadic() && !call.IsDDD {
base.FatalfAt(call.Pos(), "missed FixVariadicCall")
}
if call.Op() == ir.OCALLMETH {
base.FatalfAt(call.Pos(), "missed FixMethodCall")
}
}
// ClosureType returns the struct type used to hold all the information // ClosureType returns the struct type used to hold all the information
// needed in the closure for clo (clo must be a OCLOSURE node). // needed in the closure for clo (clo must be a OCLOSURE node).
// The address of a variable of the returned type can be cast to a func. // The address of a variable of the returned type can be cast to a func.
@ -339,6 +348,7 @@ func tcCall(n *ir.CallExpr, top int) ir.Node {
} }
typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.X) }) typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.X) })
FixVariadicCall(n)
FixMethodCall(n) FixMethodCall(n)
if t.NumResults() == 0 { if t.NumResults() == 0 {
return n return n

View file

@ -536,7 +536,7 @@ func (o *orderState) call(nn ir.Node) {
} }
n := nn.(*ir.CallExpr) n := nn.(*ir.CallExpr)
typecheck.FixVariadicCall(n) typecheck.AssertFixedCall(n)
if isFuncPCIntrinsic(n) && isIfaceOfFunc(n.Args[0]) { if isFuncPCIntrinsic(n) && isIfaceOfFunc(n.Args[0]) {
// For internal/abi.FuncPCABIxxx(fn), if fn is a defined function, // For internal/abi.FuncPCABIxxx(fn), if fn is a defined function,