Skip to content

Commit 6acac8b

Browse files
committed
cmd/compile: delay all transforms for generic funcs/methods
This change cleans up the code, by just delaying all transforms on generic function methods/functions until stenciling time. That way, we don't have extra code to decide whether to delay, or an extra value for the typecheck flag. We are already doing all possible transforms at stencil time anyway, so no changes to the stenciling code. transform.go includes a change for one case where we check for shape rather than tparam, now that we only apply transforms to stenciled functions, not generic functions. This change is to allow CONVIFACE node to be correctly inserted (needed for dictionaries), even with this strange code that doesn't add the CONVIFACE node if the concrete type is NOT huge... Change-Id: I5f1e71fab11b53385902074915b3ad85f8e753fa Reviewed-on: https://go-review.googlesource.com/c/go/+/350736 Run-TryBot: Dan Scales <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Trust: Dan Scales <[email protected]>
1 parent 988f18d commit 6acac8b

File tree

4 files changed

+37
-98
lines changed

4 files changed

+37
-98
lines changed

src/cmd/compile/internal/ir/mini.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const (
6262

6363
func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) }
6464
func (n *miniNode) SetTypecheck(x uint8) {
65-
if x > 3 {
65+
if x > 2 {
6666
panic(fmt.Sprintf("cannot SetTypecheck %d", x))
6767
}
6868
n.bits.set2(miniTypecheckShift, x)

src/cmd/compile/internal/noder/helpers.go

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,12 @@ func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) ir.Node {
9595
return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y))
9696
case ir.OADD:
9797
n := ir.NewBinaryExpr(pos, op, x, y)
98-
if x.Type().HasTParam() || y.Type().HasTParam() {
99-
// Delay transformAdd() if either arg has a type param,
100-
// since it needs to know the exact types to decide whether
101-
// to transform OADD to OADDSTR.
102-
n.SetType(typ)
103-
n.SetTypecheck(3)
104-
return n
105-
}
10698
typed(typ, n)
107-
return transformAdd(n)
99+
r := ir.Node(n)
100+
if !delayTransform() {
101+
r = transformAdd(n)
102+
}
103+
return r
108104
default:
109105
return typed(x.Type(), ir.NewBinaryExpr(pos, op, x, y))
110106
}
@@ -201,22 +197,10 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
201197

202198
func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node {
203199
n := ir.NewBinaryExpr(pos, op, x, y)
204-
if x.Type().HasTParam() || y.Type().HasTParam() {
205-
xIsInt := x.Type().IsInterface()
206-
yIsInt := y.Type().IsInterface()
207-
if !(xIsInt && !yIsInt || !xIsInt && yIsInt) {
208-
// If either arg is a type param, then we can still do the
209-
// transformCompare() if we know that one arg is an interface
210-
// and the other is not. Otherwise, we delay
211-
// transformCompare(), since it needs to know the exact types
212-
// to decide on any needed conversions.
213-
n.SetType(typ)
214-
n.SetTypecheck(3)
215-
return n
216-
}
217-
}
218200
typed(typ, n)
219-
transformCompare(n)
201+
if !delayTransform() {
202+
transformCompare(n)
203+
}
220204
return n
221205
}
222206

@@ -288,15 +272,11 @@ func method(typ *types.Type, index int) *types.Field {
288272

289273
func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node {
290274
n := ir.NewIndexExpr(pos, x, index)
291-
if x.Type().HasTParam() {
292-
// transformIndex needs to know exact type
293-
n.SetType(typ)
294-
n.SetTypecheck(3)
295-
return n
296-
}
297275
typed(typ, n)
298-
// transformIndex will modify n.Type() for OINDEXMAP.
299-
transformIndex(n)
276+
if !delayTransform() {
277+
// transformIndex will modify n.Type() for OINDEXMAP.
278+
transformIndex(n)
279+
}
300280
return n
301281
}
302282

@@ -306,14 +286,10 @@ func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) ir.Node {
306286
op = ir.OSLICE3
307287
}
308288
n := ir.NewSliceExpr(pos, op, x, low, high, max)
309-
if x.Type().HasTParam() {
310-
// transformSlice needs to know if x.Type() is a string or an array or a slice.
311-
n.SetType(typ)
312-
n.SetTypecheck(3)
313-
return n
314-
}
315289
typed(typ, n)
316-
transformSlice(n)
290+
if !delayTransform() {
291+
transformSlice(n)
292+
}
317293
return n
318294
}
319295

@@ -355,3 +331,9 @@ func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt {
355331
}
356332
return ir.NewAssignOpStmt(pos, op, x, bl)
357333
}
334+
335+
// delayTransform returns true if we should delay all transforms, because we are
336+
// creating the nodes for a generic function/method.
337+
func delayTransform() bool {
338+
return ir.CurFunc != nil && ir.CurFunc.Type().HasTParam()
339+
}

src/cmd/compile/internal/noder/stmt.go

Lines changed: 14 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
4040
return wrapname(g.pos(stmt.X), g.expr(stmt.X))
4141
case *syntax.SendStmt:
4242
n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value))
43-
if n.Chan.Type().HasTParam() || n.Value.Type().HasTParam() {
44-
// Delay transforming the send if the channel or value
45-
// have a type param.
46-
n.SetTypecheck(3)
47-
return n
43+
if !delayTransform() {
44+
transformSend(n)
4845
}
49-
transformSend(n)
5046
n.SetTypecheck(1)
5147
return n
5248
case *syntax.DeclStmt:
@@ -66,11 +62,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
6662
lhs := g.expr(stmt.Lhs)
6763
n = ir.NewAssignOpStmt(g.pos(stmt), op, lhs, rhs)
6864
}
69-
if n.X.Typecheck() == 3 {
70-
n.SetTypecheck(3)
71-
return n
65+
if !delayTransform() {
66+
transformAsOp(n)
7267
}
73-
transformAsOp(n)
7468
n.SetTypecheck(1)
7569
return n
7670
}
@@ -79,46 +73,24 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
7973
rhs := g.exprList(stmt.Rhs)
8074
names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def)
8175

82-
// We must delay transforming the assign statement if any of the
83-
// lhs or rhs nodes are also delayed, since transformAssign needs
84-
// to know the types of the left and right sides in various cases.
85-
delay := false
86-
for _, e := range lhs {
87-
if e.Type().HasTParam() || e.Typecheck() == 3 {
88-
delay = true
89-
break
90-
}
91-
}
92-
for _, e := range rhs {
93-
if e.Type().HasTParam() || e.Typecheck() == 3 {
94-
delay = true
95-
break
96-
}
97-
}
98-
9976
if len(lhs) == 1 && len(rhs) == 1 {
10077
n := ir.NewAssignStmt(g.pos(stmt), lhs[0], rhs[0])
10178
n.Def = initDefn(n, names)
10279

103-
if delay {
104-
n.SetTypecheck(3)
105-
return n
80+
if !delayTransform() {
81+
lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
82+
transformAssign(n, lhs, rhs)
83+
n.X, n.Y = lhs[0], rhs[0]
10684
}
107-
108-
lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
109-
transformAssign(n, lhs, rhs)
110-
n.X, n.Y = lhs[0], rhs[0]
11185
n.SetTypecheck(1)
11286
return n
11387
}
11488

11589
n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs)
11690
n.Def = initDefn(n, names)
117-
if delay {
118-
n.SetTypecheck(3)
119-
return n
91+
if !delayTransform() {
92+
transformAssign(n, n.Lhs, n.Rhs)
12093
}
121-
transformAssign(n, n.Lhs, n.Rhs)
12294
n.SetTypecheck(1)
12395
return n
12496

@@ -128,15 +100,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
128100
return ir.NewGoDeferStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), callOps[:]), g.expr(stmt.Call))
129101
case *syntax.ReturnStmt:
130102
n := ir.NewReturnStmt(g.pos(stmt), g.exprList(stmt.Results))
131-
for _, e := range n.Results {
132-
if e.Type().HasTParam() {
133-
// Delay transforming the return statement if any of the
134-
// return values have a type param.
135-
n.SetTypecheck(3)
136-
return n
137-
}
103+
if !delayTransform() {
104+
transformReturn(n)
138105
}
139-
transformReturn(n)
140106
n.SetTypecheck(1)
141107
return n
142108
case *syntax.IfStmt:
@@ -146,19 +112,10 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
146112
case *syntax.SelectStmt:
147113
n := g.selectStmt(stmt)
148114

149-
delay := false
150-
for _, ncase := range n.(*ir.SelectStmt).Cases {
151-
if ncase.Comm != nil && ncase.Comm.Typecheck() == 3 {
152-
delay = true
153-
break
154-
}
155-
}
156-
if delay {
157-
n.SetTypecheck(3)
158-
} else {
115+
if !delayTransform() {
159116
transformSelect(n.(*ir.SelectStmt))
160-
n.SetTypecheck(1)
161117
}
118+
n.SetTypecheck(1)
162119
return n
163120
case *syntax.SwitchStmt:
164121
return g.switchStmt(stmt)

src/cmd/compile/internal/noder/transform.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func transformCompare(n *ir.BinaryExpr) {
195195
aop, _ := typecheck.Assignop(lt, rt)
196196
if aop != ir.OXXX {
197197
types.CalcSize(lt)
198-
if lt.HasTParam() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 {
198+
if lt.HasShape() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 {
199199
l = ir.NewConvExpr(base.Pos, aop, rt, l)
200200
l.SetTypecheck(1)
201201
}

0 commit comments

Comments
 (0)