aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/ir/mini.go2
-rw-r--r--src/cmd/compile/internal/noder/helpers.go60
-rw-r--r--src/cmd/compile/internal/noder/stmt.go71
-rw-r--r--src/cmd/compile/internal/noder/transform.go2
4 files changed, 37 insertions, 98 deletions
diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go
index a7ff4ac9c7..eeb74081fb 100644
--- a/src/cmd/compile/internal/ir/mini.go
+++ b/src/cmd/compile/internal/ir/mini.go
@@ -62,7 +62,7 @@ const (
func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) }
func (n *miniNode) SetTypecheck(x uint8) {
- if x > 3 {
+ if x > 2 {
panic(fmt.Sprintf("cannot SetTypecheck %d", x))
}
n.bits.set2(miniTypecheckShift, x)
diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go
index f06dd8b065..636b5d64cd 100644
--- a/src/cmd/compile/internal/noder/helpers.go
+++ b/src/cmd/compile/internal/noder/helpers.go
@@ -95,16 +95,12 @@ func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) ir.Node {
return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y))
case ir.OADD:
n := ir.NewBinaryExpr(pos, op, x, y)
- if x.Type().HasTParam() || y.Type().HasTParam() {
- // Delay transformAdd() if either arg has a type param,
- // since it needs to know the exact types to decide whether
- // to transform OADD to OADDSTR.
- n.SetType(typ)
- n.SetTypecheck(3)
- return n
- }
typed(typ, n)
- return transformAdd(n)
+ r := ir.Node(n)
+ if !delayTransform() {
+ r = transformAdd(n)
+ }
+ return r
default:
return typed(x.Type(), ir.NewBinaryExpr(pos, op, x, y))
}
@@ -201,22 +197,10 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node {
n := ir.NewBinaryExpr(pos, op, x, y)
- if x.Type().HasTParam() || y.Type().HasTParam() {
- xIsInt := x.Type().IsInterface()
- yIsInt := y.Type().IsInterface()
- if !(xIsInt && !yIsInt || !xIsInt && yIsInt) {
- // If either arg is a type param, then we can still do the
- // transformCompare() if we know that one arg is an interface
- // and the other is not. Otherwise, we delay
- // transformCompare(), since it needs to know the exact types
- // to decide on any needed conversions.
- n.SetType(typ)
- n.SetTypecheck(3)
- return n
- }
- }
typed(typ, n)
- transformCompare(n)
+ if !delayTransform() {
+ transformCompare(n)
+ }
return n
}
@@ -288,15 +272,11 @@ func method(typ *types.Type, index int) *types.Field {
func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node {
n := ir.NewIndexExpr(pos, x, index)
- if x.Type().HasTParam() {
- // transformIndex needs to know exact type
- n.SetType(typ)
- n.SetTypecheck(3)
- return n
- }
typed(typ, n)
- // transformIndex will modify n.Type() for OINDEXMAP.
- transformIndex(n)
+ if !delayTransform() {
+ // transformIndex will modify n.Type() for OINDEXMAP.
+ transformIndex(n)
+ }
return n
}
@@ -306,14 +286,10 @@ func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) ir.Node {
op = ir.OSLICE3
}
n := ir.NewSliceExpr(pos, op, x, low, high, max)
- if x.Type().HasTParam() {
- // transformSlice needs to know if x.Type() is a string or an array or a slice.
- n.SetType(typ)
- n.SetTypecheck(3)
- return n
- }
typed(typ, n)
- transformSlice(n)
+ if !delayTransform() {
+ transformSlice(n)
+ }
return n
}
@@ -355,3 +331,9 @@ func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt {
}
return ir.NewAssignOpStmt(pos, op, x, bl)
}
+
+// delayTransform returns true if we should delay all transforms, because we are
+// creating the nodes for a generic function/method.
+func delayTransform() bool {
+ return ir.CurFunc != nil && ir.CurFunc.Type().HasTParam()
+}
diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go
index aefd9fcdaa..805a4710c4 100644
--- a/src/cmd/compile/internal/noder/stmt.go
+++ b/src/cmd/compile/internal/noder/stmt.go
@@ -40,13 +40,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
return wrapname(g.pos(stmt.X), g.expr(stmt.X))
case *syntax.SendStmt:
n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value))
- if n.Chan.Type().HasTParam() || n.Value.Type().HasTParam() {
- // Delay transforming the send if the channel or value
- // have a type param.
- n.SetTypecheck(3)
- return n
+ if !delayTransform() {
+ transformSend(n)
}
- transformSend(n)
n.SetTypecheck(1)
return n
case *syntax.DeclStmt:
@@ -66,11 +62,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
lhs := g.expr(stmt.Lhs)
n = ir.NewAssignOpStmt(g.pos(stmt), op, lhs, rhs)
}
- if n.X.Typecheck() == 3 {
- n.SetTypecheck(3)
- return n
+ if !delayTransform() {
+ transformAsOp(n)
}
- transformAsOp(n)
n.SetTypecheck(1)
return n
}
@@ -79,46 +73,24 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
rhs := g.exprList(stmt.Rhs)
names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def)
- // We must delay transforming the assign statement if any of the
- // lhs or rhs nodes are also delayed, since transformAssign needs
- // to know the types of the left and right sides in various cases.
- delay := false
- for _, e := range lhs {
- if e.Type().HasTParam() || e.Typecheck() == 3 {
- delay = true
- break
- }
- }
- for _, e := range rhs {
- if e.Type().HasTParam() || e.Typecheck() == 3 {
- delay = true
- break
- }
- }
-
if len(lhs) == 1 && len(rhs) == 1 {
n := ir.NewAssignStmt(g.pos(stmt), lhs[0], rhs[0])
n.Def = initDefn(n, names)
- if delay {
- n.SetTypecheck(3)
- return n
+ if !delayTransform() {
+ lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
+ transformAssign(n, lhs, rhs)
+ n.X, n.Y = lhs[0], rhs[0]
}
-
- lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
- transformAssign(n, lhs, rhs)
- n.X, n.Y = lhs[0], rhs[0]
n.SetTypecheck(1)
return n
}
n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs)
n.Def = initDefn(n, names)
- if delay {
- n.SetTypecheck(3)
- return n
+ if !delayTransform() {
+ transformAssign(n, n.Lhs, n.Rhs)
}
- transformAssign(n, n.Lhs, n.Rhs)
n.SetTypecheck(1)
return n
@@ -128,15 +100,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
return ir.NewGoDeferStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), callOps[:]), g.expr(stmt.Call))
case *syntax.ReturnStmt:
n := ir.NewReturnStmt(g.pos(stmt), g.exprList(stmt.Results))
- for _, e := range n.Results {
- if e.Type().HasTParam() {
- // Delay transforming the return statement if any of the
- // return values have a type param.
- n.SetTypecheck(3)
- return n
- }
+ if !delayTransform() {
+ transformReturn(n)
}
- transformReturn(n)
n.SetTypecheck(1)
return n
case *syntax.IfStmt:
@@ -146,19 +112,10 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
case *syntax.SelectStmt:
n := g.selectStmt(stmt)
- delay := false
- for _, ncase := range n.(*ir.SelectStmt).Cases {
- if ncase.Comm != nil && ncase.Comm.Typecheck() == 3 {
- delay = true
- break
- }
- }
- if delay {
- n.SetTypecheck(3)
- } else {
+ if !delayTransform() {
transformSelect(n.(*ir.SelectStmt))
- n.SetTypecheck(1)
}
+ n.SetTypecheck(1)
return n
case *syntax.SwitchStmt:
return g.switchStmt(stmt)
diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go
index 3e5cfacb97..953036eb42 100644
--- a/src/cmd/compile/internal/noder/transform.go
+++ b/src/cmd/compile/internal/noder/transform.go
@@ -195,7 +195,7 @@ func transformCompare(n *ir.BinaryExpr) {
aop, _ := typecheck.Assignop(lt, rt)
if aop != ir.OXXX {
types.CalcSize(lt)
- if lt.HasTParam() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 {
+ if lt.HasShape() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 {
l = ir.NewConvExpr(base.Pos, aop, rt, l)
l.SetTypecheck(1)
}