Skip to content

Commit

Permalink
[dev.unified] cmd/compile/internal/noder: wire RTTI for implicit conv…
Browse files Browse the repository at this point in the history
…ersions

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>
  • Loading branch information
mdempsky committed Jul 19, 2022
1 parent c846fd8 commit e376746
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 10 deletions.
75 changes: 70 additions & 5 deletions src/cmd/compile/internal/noder/reader.go
Expand Up @@ -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
}

Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
}
Expand Down
5 changes: 0 additions & 5 deletions src/cmd/compile/internal/noder/writer.go
Expand Up @@ -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 {
Expand Down

0 comments on commit e376746

Please sign in to comment.