From: Matthew Dempsky Date: Fri, 1 Jul 2022 00:58:47 +0000 (-0700) Subject: [dev.unified] cmd/compile/internal/noder: wire RTTI for implicit conversions X-Git-Tag: go1.20rc1~1807^2~21 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e376746e54;p=gostls13.git [dev.unified] cmd/compile/internal/noder: wire RTTI for implicit conversions 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 Reviewed-by: Cuong Manh Le Reviewed-by: David Chase TryBot-Result: Gopher Robot --- diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index d93859f6ef..6b47c11749 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -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 } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 6036695de1..7ad87146fb 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -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 {