Skip to content

Commit 131f981

Browse files
committed
[dev.unified] cmd/compile: make Unified IR always writes concrete type for const exprs
So we don't have to depend on typecheck pass to fixup the concrete type for some constant expressions. Previously, the problem won't show up, until CL 418475 sent, which removes an un-necessary type conversion in "append(a, b...) to help the optimization kicks in. For #53888 Change-Id: Idaecd38b7abbaa3ad5b00ff3b1fb0fd8bbeb6726 Reviewed-on: https://go-review.googlesource.com/c/go/+/418514 Run-TryBot: Cuong Manh Le <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent ae43bdc commit 131f981

File tree

3 files changed

+37
-27
lines changed

3 files changed

+37
-27
lines changed

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

+3-26
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package noder
66

77
import (
88
"fmt"
9-
"go/constant"
109

1110
"cmd/compile/internal/base"
1211
"cmd/compile/internal/ir"
@@ -53,31 +52,9 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node {
5352

5453
base.Assert(g.exprStmtOK)
5554

56-
// The gc backend expects all expressions to have a concrete type, and
57-
// types2 mostly satisfies this expectation already. But there are a few
58-
// cases where the Go spec doesn't require converting to concrete type,
59-
// and so types2 leaves them untyped. So we need to fix those up here.
60-
typ := tv.Type
61-
if basic, ok := typ.(*types2.Basic); ok && basic.Info()&types2.IsUntyped != 0 {
62-
switch basic.Kind() {
63-
case types2.UntypedNil:
64-
// ok; can appear in type switch case clauses
65-
// TODO(mdempsky): Handle as part of type switches instead?
66-
case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
67-
// Untyped rhs of non-constant shift, e.g. x << 1.0.
68-
// If we have a constant value, it must be an int >= 0.
69-
if tv.Value != nil {
70-
s := constant.ToInt(tv.Value)
71-
assert(s.Kind() == constant.Int && constant.Sign(s) >= 0)
72-
}
73-
typ = types2.Typ[types2.Uint]
74-
case types2.UntypedBool:
75-
typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
76-
case types2.UntypedString:
77-
typ = types2.Typ[types2.String] // argument to "append" or "copy" calls
78-
default:
79-
base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", basic)
80-
}
55+
typ := idealType(tv)
56+
if typ == nil {
57+
base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", tv.Type)
8158
}
8259

8360
// Constant expression.

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

+31
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"cmd/compile/internal/ir"
1212
"cmd/compile/internal/typecheck"
1313
"cmd/compile/internal/types"
14+
"cmd/compile/internal/types2"
1415
"cmd/internal/src"
1516
)
1617

@@ -220,3 +221,33 @@ func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt {
220221
}
221222
return ir.NewAssignOpStmt(pos, op, x, bl)
222223
}
224+
225+
func idealType(tv types2.TypeAndValue) types2.Type {
226+
// The gc backend expects all expressions to have a concrete type, and
227+
// types2 mostly satisfies this expectation already. But there are a few
228+
// cases where the Go spec doesn't require converting to concrete type,
229+
// and so types2 leaves them untyped. So we need to fix those up here.
230+
typ := tv.Type
231+
if basic, ok := typ.(*types2.Basic); ok && basic.Info()&types2.IsUntyped != 0 {
232+
switch basic.Kind() {
233+
case types2.UntypedNil:
234+
// ok; can appear in type switch case clauses
235+
// TODO(mdempsky): Handle as part of type switches instead?
236+
case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
237+
// Untyped rhs of non-constant shift, e.g. x << 1.0.
238+
// If we have a constant value, it must be an int >= 0.
239+
if tv.Value != nil {
240+
s := constant.ToInt(tv.Value)
241+
assert(s.Kind() == constant.Int && constant.Sign(s) >= 0)
242+
}
243+
typ = types2.Typ[types2.Uint]
244+
case types2.UntypedBool:
245+
typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
246+
case types2.UntypedString:
247+
typ = types2.Typ[types2.String] // argument to "append" or "copy" calls
248+
default:
249+
return nil
250+
}
251+
}
252+
return typ
253+
}

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,9 @@ func (w *writer) expr(expr syntax.Expr) {
14361436
if tv.Value != nil {
14371437
w.Code(exprConst)
14381438
w.pos(expr)
1439-
w.typ(tv.Type)
1439+
typ := idealType(tv)
1440+
assert(typ != nil)
1441+
w.typ(typ)
14401442
w.Value(tv.Value)
14411443

14421444
// TODO(mdempsky): These details are only important for backend

0 commit comments

Comments
 (0)