[dev.typeparams] cmd/compile: add OFUNCINST/OTYPEINST nodes for generic func/type instantiation

Expresses things more clearly, especially in cases like 'f := min[int]'
where we create a xsgeneric function instantiation, but don't immediately
call it.

min[int](2, 3) now looks like:

.   CALLFUNC tc(1) Use:1 int # min1.go:11 int
.   .   FUNCINST tc(1) FUNC-func(int, int) int # min1.go:11 FUNC-func(int, int) int
.   .   .   NAME-main.min tc(1) Class:PFUNC Offset:0 Used FUNC-func[T](T, T) T # min1.go:3
.   .   FUNCINST-Targs
.   .   .   TYPE .int Offset:0 type int
.   CALLFUNC-Args
.   .   LITERAL-2 tc(1) int # min1.go:11
.   .   LITERAL-3 tc(1) int # min1.go:11

Remove the targs parameter from ir.NewCallExpr(), not needed anymore,
since type arguments are included in the FUNCINST.

Change-Id: I23438b75288330475294d7ace239ba64acfa641e
Reviewed-on: https://go-review.googlesource.com/c/go/+/288951
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Dan Scales <danscales@google.com>
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Dan Scales 2021-02-02 12:17:57 -08:00
parent 0d2d6c7464
commit e633f343ba
19 changed files with 180 additions and 189 deletions

View file

@ -83,13 +83,13 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
// TODO(mdempsky): This should not be so difficult.
if fun.Op() == ir.OTYPE {
// Actually a type conversion, not a function call.
n := ir.NewCallExpr(pos, ir.OCALL, fun, nil, args)
n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
return typecheck.Expr(n)
}
if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 {
// Call to a builtin function.
n := ir.NewCallExpr(pos, ir.OCALL, fun, nil, args)
n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
n.IsDDD = dots
switch fun.BuiltinOp {
case ir.OCLOSE, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN:
@ -116,20 +116,10 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
}
}
var targs []ir.Node
if indexExpr, ok := fun.(*ir.IndexExpr); ok {
if indexExpr.Index.Op() == ir.OLIST {
// Called function is an instantiated generic function
fun = indexExpr.X
// Don't need to copy, since the node list was just created
targs = indexExpr.Index.(*ir.ListExpr).List
}
}
n := ir.NewCallExpr(pos, ir.OCALL, fun, targs, args)
n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
n.IsDDD = dots
if targs == nil {
if n.X.Op() != ir.OFUNCINST {
// If no type params, still do normal typechecking, since we're
// still missing some things done by tcCall below (mainly
// typecheckargs and typecheckaste).
@ -233,12 +223,7 @@ func method(typ *types.Type, index int) *types.Field {
return types.ReceiverBaseType(typ).Methods().Index(index)
}
func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node {
if index.Op() == ir.OLIST {
n := ir.NewIndexExpr(pos, x, index)
typed(typ, n)
return n
}
func Index(pos src.XPos, x, index ir.Node) ir.Node {
// TODO(mdempsky): Avoid typecheck.Expr (which will call tcIndex)
return typecheck.Expr(ir.NewIndexExpr(pos, x, index))
}