]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.unified] cmd/compile/internal/noder: wire RTTI for implicit conversions
authorMatthew Dempsky <mdempsky@google.com>
Fri, 1 Jul 2022 00:58:47 +0000 (17:58 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 19 Jul 2022 23:07:20 +0000 (23:07 +0000)
This CL updates Unified IR to set the TypeWord and SrcRType fields on
interface conversions, which will be necessary for dictionary support
shortly.

Change-Id: I9486b417f514ba4ec2ee8036194aa9ae3ad0ad93
Reviewed-on: https://go-review.googlesource.com/c/go/+/415575
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

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

index d93859f6ef85255878bfea955a2017c0c6ce1efc..6b47c11749ddbf356a1252cd3ac7b7d54231b24d 100644 (file)
@@ -1399,6 +1399,18 @@ func (r *reader) forStmt(label *types.Sym) ir.Node {
                }
                rang.Def = r.initDefn(rang, names)
                rang.Label = label
+
+               {
+                       keyType, valueType := rangeTypes(pos, x.Type())
+
+                       if rang.Key != nil {
+                               rang.KeyTypeWord, rang.KeySrcRType = convRTTI(pos, rang.Key.Type(), keyType)
+                       }
+                       if rang.Value != nil {
+                               rang.ValueTypeWord, rang.ValueSrcRType = convRTTI(pos, rang.Value.Type(), valueType)
+                       }
+               }
+
                return rang
        }
 
@@ -1414,6 +1426,28 @@ func (r *reader) forStmt(label *types.Sym) ir.Node {
        return stmt
 }
 
+// rangeTypes returns the types of values produced by ranging over a
+// value of type typ.
+func rangeTypes(pos src.XPos, typ *types.Type) (key, value *types.Type) {
+       switch typ.Kind() {
+       default:
+               base.FatalfAt(pos, "unexpected range type: %v", typ)
+               panic("unreachable")
+       case types.TPTR: // must be pointer to array
+               typ = typ.Elem()
+               base.AssertfAt(typ.Kind() == types.TARRAY, pos, "want array type, have %v", typ)
+               fallthrough
+       case types.TARRAY, types.TSLICE:
+               return types.Types[types.TINT], typ.Elem()
+       case types.TSTRING:
+               return types.Types[types.TINT], types.RuneType
+       case types.TMAP:
+               return typ.Key(), typ.Elem()
+       case types.TCHAN:
+               return typ.Elem(), nil
+       }
+}
+
 func (r *reader) ifStmt() ir.Node {
        r.Sync(pkgbits.SyncIfStmt)
        r.openScope()
@@ -1803,14 +1837,42 @@ func (r *reader) expr() (res ir.Node) {
                        base.ErrorExit() // harsh, but prevents constructing invalid IR
                }
 
-               n := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x))
-               if implicit && n.Op() != ir.OLITERAL {
-                       n.(ImplicitNode).SetImplicit(true)
+               n := ir.NewConvExpr(pos, ir.OCONV, typ, x)
+               n.TypeWord, n.SrcRType = convRTTI(pos, typ, x.Type())
+               if implicit {
+                       n.SetImplicit(true)
                }
-               return n
+               return typecheck.Expr(n)
        }
 }
 
+// convRTTI returns the TypeWord and SrcRType expressions appropriate
+// for a conversion from src to dst.
+func convRTTI(pos src.XPos, dst, src *types.Type) (typeWord, srcRType ir.Node) {
+       if !dst.IsInterface() {
+               return
+       }
+
+       // See reflectdata.ConvIfaceTypeWord.
+       switch {
+       case dst.IsEmptyInterface():
+               if !src.IsInterface() {
+                       typeWord = reflectdata.TypePtrAt(pos, src) // direct eface construction
+               }
+       case !src.IsInterface():
+               typeWord = reflectdata.ITabAddrAt(pos, src, dst) // direct iface construction
+       default:
+               typeWord = reflectdata.TypePtrAt(pos, dst) // convI2I
+       }
+
+       // See reflectdata.ConvIfaceSrcRType.
+       if !src.IsInterface() {
+               srcRType = reflectdata.TypePtrAt(pos, src)
+       }
+
+       return
+}
+
 func (r *reader) optExpr() ir.Node {
        if r.Bool() {
                return r.expr()
@@ -1841,7 +1903,10 @@ func (r *reader) multiExpr() []ir.Node {
 
                        res := ir.Node(tmp)
                        if r.Bool() {
-                               res = typecheck.Expr(Implicit(ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)))
+                               n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
+                               n.TypeWord, n.SrcRType = convRTTI(pos, n.Type(), n.X.Type())
+                               n.SetImplicit(true)
+                               res = typecheck.Expr(n)
                        }
                        results[i] = res
                }
index 6036695de130e982c8654ab3e6b10b2cc51ef46c..7ad87146fb06e290b6350fc06d2979006e371e5e 100644 (file)
@@ -1260,11 +1260,6 @@ func (w *writer) forStmt(stmt *syntax.ForStmt) {
 
        if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
                w.pos(rang)
-               // TODO(mdempsky): For !rang.Def, we need to handle implicit
-               // conversions; e.g., see #53328.
-               //
-               // This is tricky, because the assignments aren't introduced until
-               // lowering in walk.
                w.assignList(rang.Lhs)
                w.expr(rang.X)
        } else {