]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.unified] cmd/compile: make Unified IR always writes concrete type for const...
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Wed, 20 Jul 2022 13:27:58 +0000 (20:27 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Fri, 22 Jul 2022 16:26:22 +0000 (16:26 +0000)
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 <cuong.manhle.vn@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

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

index a1160d42c44030bd8582adeb79d4d1de4d7497fe..54b07c39f4940516cc047b4a5b9dd70ba575bd31 100644 (file)
@@ -6,7 +6,6 @@ package noder
 
 import (
        "fmt"
-       "go/constant"
 
        "cmd/compile/internal/base"
        "cmd/compile/internal/ir"
@@ -53,31 +52,9 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node {
 
        base.Assert(g.exprStmtOK)
 
-       // The gc backend expects all expressions to have a concrete type, and
-       // types2 mostly satisfies this expectation already. But there are a few
-       // cases where the Go spec doesn't require converting to concrete type,
-       // and so types2 leaves them untyped. So we need to fix those up here.
-       typ := tv.Type
-       if basic, ok := typ.(*types2.Basic); ok && basic.Info()&types2.IsUntyped != 0 {
-               switch basic.Kind() {
-               case types2.UntypedNil:
-                       // ok; can appear in type switch case clauses
-                       // TODO(mdempsky): Handle as part of type switches instead?
-               case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
-                       // Untyped rhs of non-constant shift, e.g. x << 1.0.
-                       // If we have a constant value, it must be an int >= 0.
-                       if tv.Value != nil {
-                               s := constant.ToInt(tv.Value)
-                               assert(s.Kind() == constant.Int && constant.Sign(s) >= 0)
-                       }
-                       typ = types2.Typ[types2.Uint]
-               case types2.UntypedBool:
-                       typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
-               case types2.UntypedString:
-                       typ = types2.Typ[types2.String] // argument to "append" or "copy" calls
-               default:
-                       base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", basic)
-               }
+       typ := idealType(tv)
+       if typ == nil {
+               base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", tv.Type)
        }
 
        // Constant expression.
index 8efcef26cf24162f1cf93d0dd9faa8decdb322c8..40f80ab528d247a353d997bde58be8edca906253 100644 (file)
@@ -11,6 +11,7 @@ import (
        "cmd/compile/internal/ir"
        "cmd/compile/internal/typecheck"
        "cmd/compile/internal/types"
+       "cmd/compile/internal/types2"
        "cmd/internal/src"
 )
 
@@ -220,3 +221,33 @@ func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt {
        }
        return ir.NewAssignOpStmt(pos, op, x, bl)
 }
+
+func idealType(tv types2.TypeAndValue) types2.Type {
+       // The gc backend expects all expressions to have a concrete type, and
+       // types2 mostly satisfies this expectation already. But there are a few
+       // cases where the Go spec doesn't require converting to concrete type,
+       // and so types2 leaves them untyped. So we need to fix those up here.
+       typ := tv.Type
+       if basic, ok := typ.(*types2.Basic); ok && basic.Info()&types2.IsUntyped != 0 {
+               switch basic.Kind() {
+               case types2.UntypedNil:
+                       // ok; can appear in type switch case clauses
+                       // TODO(mdempsky): Handle as part of type switches instead?
+               case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
+                       // Untyped rhs of non-constant shift, e.g. x << 1.0.
+                       // If we have a constant value, it must be an int >= 0.
+                       if tv.Value != nil {
+                               s := constant.ToInt(tv.Value)
+                               assert(s.Kind() == constant.Int && constant.Sign(s) >= 0)
+                       }
+                       typ = types2.Typ[types2.Uint]
+               case types2.UntypedBool:
+                       typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
+               case types2.UntypedString:
+                       typ = types2.Typ[types2.String] // argument to "append" or "copy" calls
+               default:
+                       return nil
+               }
+       }
+       return typ
+}
index 09afbcdffbfb8cc1841c772c1e4e359b84be354d..ac08022c34b0f12841a38a3111498546ca0eca70 100644 (file)
@@ -1436,7 +1436,9 @@ func (w *writer) expr(expr syntax.Expr) {
                if tv.Value != nil {
                        w.Code(exprConst)
                        w.pos(expr)
-                       w.typ(tv.Type)
+                       typ := idealType(tv)
+                       assert(typ != nil)
+                       w.typ(typ)
                        w.Value(tv.Value)
 
                        // TODO(mdempsky): These details are only important for backend