mirror of https://github.com/golang/go.git
[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>
This commit is contained in:
parent
fc72b7705d
commit
9b70178d58
|
|
@ -1390,17 +1390,10 @@ func (r *reader) forStmt(label *types.Sym) ir.Node {
|
||||||
|
|
||||||
if r.Bool() {
|
if r.Bool() {
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
|
rang := ir.NewRangeStmt(pos, nil, nil, nil, nil)
|
||||||
|
rang.Label = label
|
||||||
|
|
||||||
names, lhs := r.assignList()
|
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 {
|
if len(lhs) >= 1 {
|
||||||
rang.Key = lhs[0]
|
rang.Key = lhs[0]
|
||||||
if len(lhs) >= 2 {
|
if len(lhs) >= 2 {
|
||||||
|
|
@ -1408,10 +1401,13 @@ func (r *reader) forStmt(label *types.Sym) ir.Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rang.Def = r.initDefn(rang, names)
|
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 {
|
if rang.Key != nil {
|
||||||
rang.KeyTypeWord, rang.KeySrcRType = convRTTI(pos, rang.Key.Type(), keyType)
|
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
|
return rang
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1741,7 +1740,7 @@ func (r *reader) expr() (res ir.Node) {
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ir.OINDEXMAP:
|
case ir.OINDEXMAP:
|
||||||
n := n.(*ir.IndexExpr)
|
n := n.(*ir.IndexExpr)
|
||||||
n.RType = reflectdata.TypePtrAt(pos, x.Type())
|
n.RType = r.rtype(pos)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
|
|
||||||
|
|
@ -1762,10 +1761,12 @@ func (r *reader) expr() (res ir.Node) {
|
||||||
x := r.expr()
|
x := r.expr()
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
typ := r.exprType(false)
|
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 {
|
if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
|
||||||
assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType)
|
assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType)
|
||||||
assert.SrcRType = reflectdata.TypePtrAt(pos, x.Type())
|
assert.SrcRType = srcRType
|
||||||
assert.ITab = typ.ITab
|
assert.ITab = typ.ITab
|
||||||
return typed(typ.Type(), assert)
|
return typed(typ.Type(), assert)
|
||||||
}
|
}
|
||||||
|
|
@ -1810,16 +1811,16 @@ func (r *reader) expr() (res ir.Node) {
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ir.OAPPEND:
|
case ir.OAPPEND:
|
||||||
n := n.(*ir.CallExpr)
|
n := n.(*ir.CallExpr)
|
||||||
n.RType = reflectdata.TypePtrAt(pos, n.Type().Elem())
|
n.RType = r.rtype(pos)
|
||||||
case ir.OCOPY:
|
case ir.OCOPY:
|
||||||
n := n.(*ir.BinaryExpr)
|
n := n.(*ir.BinaryExpr)
|
||||||
n.RType = reflectdata.TypePtrAt(pos, n.X.Type().Elem())
|
n.RType = r.rtype(pos)
|
||||||
case ir.ODELETE:
|
case ir.ODELETE:
|
||||||
n := n.(*ir.CallExpr)
|
n := n.(*ir.CallExpr)
|
||||||
n.RType = reflectdata.TypePtrAt(pos, n.Args[0].Type())
|
n.RType = r.rtype(pos)
|
||||||
case ir.OUNSAFESLICE:
|
case ir.OUNSAFESLICE:
|
||||||
n := n.(*ir.BinaryExpr)
|
n := n.(*ir.BinaryExpr)
|
||||||
n.RType = reflectdata.TypePtrAt(pos, n.Type().Elem())
|
n.RType = r.rtype(pos)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
|
|
||||||
|
|
@ -1828,14 +1829,7 @@ func (r *reader) expr() (res ir.Node) {
|
||||||
typ := r.exprType(false)
|
typ := r.exprType(false)
|
||||||
extra := r.exprs()
|
extra := r.exprs()
|
||||||
n := typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr)
|
n := typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr)
|
||||||
switch n.Op() {
|
n.RType = r.rtype(pos)
|
||||||
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())
|
|
||||||
}
|
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case exprNew:
|
case exprNew:
|
||||||
|
|
@ -1969,6 +1963,10 @@ func (r *reader) compLit() ir.Node {
|
||||||
if typ.Kind() == types.TFORW {
|
if typ.Kind() == types.TFORW {
|
||||||
base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
|
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
|
isStruct := typ.Kind() == types.TSTRUCT
|
||||||
|
|
||||||
elems := make([]ir.Node, r.Len())
|
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))
|
lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems))
|
||||||
switch lit.Op() {
|
if rtype != nil {
|
||||||
case ir.OMAPLIT:
|
|
||||||
lit := lit.(*ir.CompLitExpr)
|
lit := lit.(*ir.CompLitExpr)
|
||||||
lit.RType = reflectdata.TypePtrAt(pos, typ)
|
lit.RType = rtype
|
||||||
}
|
}
|
||||||
if typ0.IsPtr() {
|
if typ0.IsPtr() {
|
||||||
lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
|
lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
|
||||||
|
|
@ -2060,6 +2057,12 @@ func (r *reader) exprs() []ir.Node {
|
||||||
return nodes
|
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 {
|
func (r *reader) exprType(nilOK bool) ir.Node {
|
||||||
r.Sync(pkgbits.SyncExprType)
|
r.Sync(pkgbits.SyncExprType)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1299,6 +1299,11 @@ func (w *writer) forStmt(stmt *syntax.ForStmt) {
|
||||||
w.pos(rang)
|
w.pos(rang)
|
||||||
w.assignList(rang.Lhs)
|
w.assignList(rang.Lhs)
|
||||||
w.expr(rang.X)
|
w.expr(rang.X)
|
||||||
|
|
||||||
|
xtyp := w.p.typeOf(rang.X)
|
||||||
|
if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap {
|
||||||
|
w.rtype(xtyp)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.pos(stmt)
|
w.pos(stmt)
|
||||||
w.stmt(stmt.Init)
|
w.stmt(stmt.Init)
|
||||||
|
|
@ -1549,8 +1554,10 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
case *syntax.IndexExpr:
|
case *syntax.IndexExpr:
|
||||||
_ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation
|
_ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation
|
||||||
|
|
||||||
|
xtyp := w.p.typeOf(expr.X)
|
||||||
|
|
||||||
var keyType types2.Type
|
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()
|
keyType = mapType.Key()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1558,6 +1565,9 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
w.expr(expr.X)
|
w.expr(expr.X)
|
||||||
w.pos(expr)
|
w.pos(expr)
|
||||||
w.implicitConvExpr(expr, keyType, expr.Index)
|
w.implicitConvExpr(expr, keyType, expr.Index)
|
||||||
|
if keyType != nil {
|
||||||
|
w.rtype(xtyp)
|
||||||
|
}
|
||||||
|
|
||||||
case *syntax.SliceExpr:
|
case *syntax.SliceExpr:
|
||||||
w.Code(exprSlice)
|
w.Code(exprSlice)
|
||||||
|
|
@ -1574,6 +1584,7 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
w.expr(expr.X)
|
w.expr(expr.X)
|
||||||
w.pos(expr)
|
w.pos(expr)
|
||||||
w.exprType(iface, expr.Type, false)
|
w.exprType(iface, expr.Type, false)
|
||||||
|
w.rtype(iface)
|
||||||
|
|
||||||
case *syntax.Operation:
|
case *syntax.Operation:
|
||||||
if expr.Y == nil {
|
if expr.Y == nil {
|
||||||
|
|
@ -1622,8 +1633,9 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if name, ok := unparen(expr.Fun).(*syntax.Name); ok && tv.IsBuiltin() {
|
var rtype types2.Type
|
||||||
switch name.Value {
|
if tv.IsBuiltin() {
|
||||||
|
switch obj, _ := lookupObj(w.p.info, expr.Fun); obj.Name() {
|
||||||
case "make":
|
case "make":
|
||||||
assert(len(expr.ArgList) >= 1)
|
assert(len(expr.ArgList) >= 1)
|
||||||
assert(!expr.HasDots)
|
assert(!expr.HasDots)
|
||||||
|
|
@ -1632,6 +1644,19 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
w.pos(expr)
|
w.pos(expr)
|
||||||
w.exprType(nil, expr.ArgList[0], false)
|
w.exprType(nil, expr.ArgList[0], false)
|
||||||
w.exprs(expr.ArgList[1:])
|
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
|
return
|
||||||
|
|
||||||
case "new":
|
case "new":
|
||||||
|
|
@ -1642,6 +1667,23 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
w.pos(expr)
|
w.pos(expr)
|
||||||
w.exprType(nil, expr.ArgList[0], false)
|
w.exprType(nil, expr.ArgList[0], false)
|
||||||
return
|
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.multiExpr(expr, paramType, expr.ArgList)
|
||||||
w.Bool(expr.HasDots)
|
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) {
|
func (w *writer) optExpr(expr syntax.Expr) {
|
||||||
if w.Bool(expr != nil) {
|
if w.Bool(expr != nil) {
|
||||||
w.expr(expr)
|
w.expr(expr)
|
||||||
|
|
@ -1757,12 +1806,13 @@ func (w *writer) compLit(lit *syntax.CompositeLit) {
|
||||||
}
|
}
|
||||||
var keyType, elemType types2.Type
|
var keyType, elemType types2.Type
|
||||||
var structType *types2.Struct
|
var structType *types2.Struct
|
||||||
switch typ := types2.CoreType(typ).(type) {
|
switch typ0 := typ; typ := types2.CoreType(typ).(type) {
|
||||||
default:
|
default:
|
||||||
w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
|
w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
|
||||||
case *types2.Array:
|
case *types2.Array:
|
||||||
elemType = typ.Elem()
|
elemType = typ.Elem()
|
||||||
case *types2.Map:
|
case *types2.Map:
|
||||||
|
w.rtype(typ0)
|
||||||
keyType, elemType = typ.Key(), typ.Elem()
|
keyType, elemType = typ.Key(), typ.Elem()
|
||||||
case *types2.Slice:
|
case *types2.Slice:
|
||||||
elemType = typ.Elem()
|
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) {
|
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)
|
base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,4 +112,5 @@ const (
|
||||||
SyncOptLabel
|
SyncOptLabel
|
||||||
|
|
||||||
SyncMultiExpr
|
SyncMultiExpr
|
||||||
|
SyncRType
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue