diff options
-rw-r--r-- | src/cmd/compile/internal/ir/mini.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/helpers.go | 60 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/stmt.go | 71 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/transform.go | 2 |
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) } |