diff options
author | Matthew Dempsky <mdempsky@google.com> | 2022-07-22 23:33:30 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2022-07-28 07:13:28 +0000 |
commit | 9b70178d58060764cbaedf3d4542bd67f9aafede (patch) | |
tree | d5ff314135b507a20b29028459f23bd576a296db | |
parent | fc72b7705d67f432fb6a570f84df9e8840eec226 (diff) | |
download | go-9b70178d58060764cbaedf3d4542bd67f9aafede.tar.gz go-9b70178d58060764cbaedf3d4542bd67f9aafede.zip |
[dev.unified] cmd/compile: write RTTI into unified IR export data
This CL adds `rtype` methods for unified IR for writing/reading types
that need to have their *runtime._type value available.
For now, this just builds on the existing type writing/reading
mechanics and calling reflectdata.TypePtrAt; but longer term, reading
of derived types can be changed to use dictionary lookups instead.
Change-Id: I6f803b84546fa7df2877a8a3bcbf2623e4b03449
Reviewed-on: https://go-review.googlesource.com/c/go/+/419456
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
-rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 59 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 63 | ||||
-rw-r--r-- | src/internal/pkgbits/sync.go | 1 |
3 files changed, 91 insertions, 32 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 6b7ac5494f..6692446792 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1390,17 +1390,10 @@ func (r *reader) forStmt(label *types.Sym) ir.Node { if r.Bool() { pos := r.pos() + rang := ir.NewRangeStmt(pos, nil, nil, nil, nil) + rang.Label = label names, lhs := r.assignList() - x := r.expr() - - body := r.blockStmt() - r.closeAnotherScope() - - rang := ir.NewRangeStmt(pos, nil, nil, x, body) - if x.Type().IsMap() { - rang.RType = reflectdata.TypePtrAt(pos, x.Type()) - } if len(lhs) >= 1 { rang.Key = lhs[0] if len(lhs) >= 2 { @@ -1408,10 +1401,13 @@ func (r *reader) forStmt(label *types.Sym) ir.Node { } } rang.Def = r.initDefn(rang, names) - rang.Label = label + rang.X = r.expr() + if rang.X.Type().IsMap() { + rang.RType = r.rtype(pos) + } { - keyType, valueType := rangeTypes(pos, x.Type()) + keyType, valueType := rangeTypes(pos, rang.X.Type()) if rang.Key != nil { rang.KeyTypeWord, rang.KeySrcRType = convRTTI(pos, rang.Key.Type(), keyType) @@ -1421,6 +1417,9 @@ func (r *reader) forStmt(label *types.Sym) ir.Node { } } + rang.Body = r.blockStmt() + r.closeAnotherScope() + return rang } @@ -1741,7 +1740,7 @@ func (r *reader) expr() (res ir.Node) { switch n.Op() { case ir.OINDEXMAP: n := n.(*ir.IndexExpr) - n.RType = reflectdata.TypePtrAt(pos, x.Type()) + n.RType = r.rtype(pos) } return n @@ -1762,10 +1761,12 @@ func (r *reader) expr() (res ir.Node) { x := r.expr() pos := r.pos() typ := r.exprType(false) + srcRType := r.rtype(pos) + // TODO(mdempsky): Always emit ODYNAMICDOTTYPE for uniformity? if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE { assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType) - assert.SrcRType = reflectdata.TypePtrAt(pos, x.Type()) + assert.SrcRType = srcRType assert.ITab = typ.ITab return typed(typ.Type(), assert) } @@ -1810,16 +1811,16 @@ func (r *reader) expr() (res ir.Node) { switch n.Op() { case ir.OAPPEND: n := n.(*ir.CallExpr) - n.RType = reflectdata.TypePtrAt(pos, n.Type().Elem()) + n.RType = r.rtype(pos) case ir.OCOPY: n := n.(*ir.BinaryExpr) - n.RType = reflectdata.TypePtrAt(pos, n.X.Type().Elem()) + n.RType = r.rtype(pos) case ir.ODELETE: n := n.(*ir.CallExpr) - n.RType = reflectdata.TypePtrAt(pos, n.Args[0].Type()) + n.RType = r.rtype(pos) case ir.OUNSAFESLICE: n := n.(*ir.BinaryExpr) - n.RType = reflectdata.TypePtrAt(pos, n.Type().Elem()) + n.RType = r.rtype(pos) } return n @@ -1828,14 +1829,7 @@ func (r *reader) expr() (res ir.Node) { typ := r.exprType(false) extra := r.exprs() n := typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr) - switch n.Op() { - case ir.OMAKECHAN: - n.RType = reflectdata.TypePtrAt(pos, typ.Type()) - case ir.OMAKEMAP: - n.RType = reflectdata.TypePtrAt(pos, typ.Type()) - case ir.OMAKESLICE: - n.RType = reflectdata.TypePtrAt(pos, typ.Type().Elem()) - } + n.RType = r.rtype(pos) return n case exprNew: @@ -1969,6 +1963,10 @@ func (r *reader) compLit() ir.Node { if typ.Kind() == types.TFORW { base.FatalfAt(pos, "unresolved composite literal type: %v", typ) } + var rtype ir.Node + if typ.IsMap() { + rtype = r.rtype(pos) + } isStruct := typ.Kind() == types.TSTRUCT elems := make([]ir.Node, r.Len()) @@ -1987,10 +1985,9 @@ func (r *reader) compLit() ir.Node { } lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems)) - switch lit.Op() { - case ir.OMAPLIT: + if rtype != nil { lit := lit.(*ir.CompLitExpr) - lit.RType = reflectdata.TypePtrAt(pos, typ) + lit.RType = rtype } if typ0.IsPtr() { lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit)) @@ -2060,6 +2057,12 @@ func (r *reader) exprs() []ir.Node { return nodes } +func (r *reader) rtype(pos src.XPos) ir.Node { + r.Sync(pkgbits.SyncRType) + // TODO(mdempsky): For derived types, use dictionary instead. + return reflectdata.TypePtrAt(pos, r.typ()) +} + func (r *reader) exprType(nilOK bool) ir.Node { r.Sync(pkgbits.SyncExprType) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 93e81bdc82..5dd252a2a5 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1299,6 +1299,11 @@ func (w *writer) forStmt(stmt *syntax.ForStmt) { w.pos(rang) w.assignList(rang.Lhs) w.expr(rang.X) + + xtyp := w.p.typeOf(rang.X) + if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap { + w.rtype(xtyp) + } } else { w.pos(stmt) w.stmt(stmt.Init) @@ -1549,8 +1554,10 @@ func (w *writer) expr(expr syntax.Expr) { case *syntax.IndexExpr: _ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation + xtyp := w.p.typeOf(expr.X) + var keyType types2.Type - if mapType, ok := types2.CoreType(w.p.typeOf(expr.X)).(*types2.Map); ok { + if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok { keyType = mapType.Key() } @@ -1558,6 +1565,9 @@ func (w *writer) expr(expr syntax.Expr) { w.expr(expr.X) w.pos(expr) w.implicitConvExpr(expr, keyType, expr.Index) + if keyType != nil { + w.rtype(xtyp) + } case *syntax.SliceExpr: w.Code(exprSlice) @@ -1574,6 +1584,7 @@ func (w *writer) expr(expr syntax.Expr) { w.expr(expr.X) w.pos(expr) w.exprType(iface, expr.Type, false) + w.rtype(iface) case *syntax.Operation: if expr.Y == nil { @@ -1622,8 +1633,9 @@ func (w *writer) expr(expr syntax.Expr) { break } - if name, ok := unparen(expr.Fun).(*syntax.Name); ok && tv.IsBuiltin() { - switch name.Value { + var rtype types2.Type + if tv.IsBuiltin() { + switch obj, _ := lookupObj(w.p.info, expr.Fun); obj.Name() { case "make": assert(len(expr.ArgList) >= 1) assert(!expr.HasDots) @@ -1632,6 +1644,19 @@ func (w *writer) expr(expr syntax.Expr) { w.pos(expr) w.exprType(nil, expr.ArgList[0], false) w.exprs(expr.ArgList[1:]) + + typ := w.p.typeOf(expr) + switch coreType := types2.CoreType(typ).(type) { + default: + w.p.fatalf(expr, "unexpected core type: %v", coreType) + case *types2.Chan: + w.rtype(typ) + case *types2.Map: + w.rtype(typ) + case *types2.Slice: + w.rtype(sliceElem(typ)) + } + return case "new": @@ -1642,6 +1667,23 @@ func (w *writer) expr(expr syntax.Expr) { w.pos(expr) w.exprType(nil, expr.ArgList[0], false) return + + case "append": + rtype = sliceElem(w.p.typeOf(expr)) + case "copy": + typ := w.p.typeOf(expr.ArgList[0]) + if tuple, ok := typ.(*types2.Tuple); ok { // "copy(g())" + typ = tuple.At(0).Type() + } + rtype = sliceElem(typ) + case "delete": + typ := w.p.typeOf(expr.ArgList[0]) + if tuple, ok := typ.(*types2.Tuple); ok { // "delete(g())" + typ = tuple.At(0).Type() + } + rtype = typ + case "Slice": + rtype = sliceElem(w.p.typeOf(expr)) } } @@ -1676,9 +1718,16 @@ func (w *writer) expr(expr syntax.Expr) { w.multiExpr(expr, paramType, expr.ArgList) w.Bool(expr.HasDots) + if rtype != nil { + w.rtype(rtype) + } } } +func sliceElem(typ types2.Type) types2.Type { + return types2.CoreType(typ).(*types2.Slice).Elem() +} + func (w *writer) optExpr(expr syntax.Expr) { if w.Bool(expr != nil) { w.expr(expr) @@ -1757,12 +1806,13 @@ func (w *writer) compLit(lit *syntax.CompositeLit) { } var keyType, elemType types2.Type var structType *types2.Struct - switch typ := types2.CoreType(typ).(type) { + switch typ0 := typ; typ := types2.CoreType(typ).(type) { default: w.p.fatalf(lit, "unexpected composite literal type: %v", typ) case *types2.Array: elemType = typ.Elem() case *types2.Map: + w.rtype(typ0) keyType, elemType = typ.Key(), typ.Elem() case *types2.Slice: elemType = typ.Elem() @@ -1833,6 +1883,11 @@ func (w *writer) exprs(exprs []syntax.Expr) { } } +func (w *writer) rtype(typ types2.Type) { + w.Sync(pkgbits.SyncRType) + w.typ(typ) +} + func (w *writer) exprType(iface types2.Type, typ syntax.Expr, nilOK bool) { base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface) diff --git a/src/internal/pkgbits/sync.go b/src/internal/pkgbits/sync.go index 6a5999eb6b..54e478d932 100644 --- a/src/internal/pkgbits/sync.go +++ b/src/internal/pkgbits/sync.go @@ -112,4 +112,5 @@ const ( SyncOptLabel SyncMultiExpr + SyncRType ) |