]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.unified] cmd/compile: add RType fields
authorMatthew Dempsky <mdempsky@google.com>
Tue, 21 Jun 2022 06:21:16 +0000 (23:21 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 23 Jun 2022 21:52:30 +0000 (21:52 +0000)
This CL adds RType/ITab fields to IR nodes that (may) ultimately
become runtime calls that require a *runtime._type or *runtime.itab
argument. It also updates the corresponding reflectdata IR helpers to
use these fields in preference of calling TypePtr/ITabAddr.

Subsequent CLs will start updating the GOEXPERIMENT=unified frontend
to set the RType fields, and incrementally switch the reflectdata
helpers to require them.

Passes toolstash -cmp.

Change-Id: I30e31d91f0a53961e3d6d872d7b5f9df2ec5074c
Reviewed-on: https://go-review.googlesource.com/c/go/+/413358
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/ir/expr.go
src/cmd/compile/internal/ir/stmt.go
src/cmd/compile/internal/reflectdata/helpers.go
src/cmd/compile/internal/walk/convert.go

index 27dd390efcc4d9e0c342b603b59cb0b97cd24c6c..4a8db70904bb67fdc08661f87fc3708822d942dd 100644 (file)
@@ -119,8 +119,9 @@ func (n *BasicLit) SetVal(val constant.Value) { n.val = val }
 // or Op(X, Y) for builtin functions that do not become calls.
 type BinaryExpr struct {
        miniExpr
-       X Node
-       Y Node
+       X     Node
+       Y     Node
+       RType Node `mknode:"-"` // see reflectdata/helpers.go
 }
 
 func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
@@ -148,6 +149,7 @@ type CallExpr struct {
        origNode
        X         Node
        Args      Nodes
+       RType     Node    `mknode:"-"` // see reflectdata/helpers.go
        KeepAlive []*Name // vars to be kept alive until call returns
        IsDDD     bool
        NoInline  bool
@@ -247,6 +249,17 @@ type ConvExpr struct {
        miniExpr
        X Node
 
+       // For implementing OCONVIFACE expressions.
+       //
+       // TypeWord is an expression yielding a *runtime._type or
+       // *runtime.itab value to go in the type word of the iface/eface
+       // result. See reflectdata.ConvIfaceTypeWord for further details.
+       //
+       // SrcRType is an expression yielding a *runtime._type value for X,
+       // if it's not pointer-shaped and needs to be heap allocated.
+       TypeWord Node `mknode:"-"`
+       SrcRType Node `mknode:"-"`
+
        // For -d=checkptr instrumentation of conversions from
        // unsafe.Pointer to *Elem or *[Len]Elem.
        //
@@ -285,6 +298,7 @@ type IndexExpr struct {
        miniExpr
        X        Node
        Index    Node
+       RType    Node `mknode:"-"` // see reflectdata/helpers.go
        Assigned bool
 }
 
@@ -395,8 +409,9 @@ func (n *LogicalExpr) SetOp(op Op) {
 // but *not* OMAKE (that's a pre-typechecking CallExpr).
 type MakeExpr struct {
        miniExpr
-       Len Node
-       Cap Node
+       RType Node `mknode:"-"` // see reflectdata/helpers.go
+       Len   Node
+       Cap   Node
 }
 
 func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr {
@@ -633,7 +648,7 @@ type TypeAssertExpr struct {
 
        // Runtime type information provided by walkDotType for
        // assertions from non-empty interface to concrete type.
-       ITab *AddrExpr `mknode:"-"` // *runtime.itab for Type implementing X's type
+       ITab Node `mknode:"-"` // *runtime.itab for Type implementing X's type
 }
 
 func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr {
index c46debce36b898583ccd9ec3276fc01ef9af1fb4..6a82df58f855b9da2119064b26d377a8cf1813e6 100644 (file)
@@ -333,6 +333,7 @@ type RangeStmt struct {
        Label    *types.Sym
        Def      bool
        X        Node
+       RType    Node `mknode:"-"` // see reflectdata/helpers.go
        Key      Node
        Value    Node
        Body     Nodes
index 61d1660773f1889d3bf6770c19f05538e837f4a2..4d85dea74daa9a184b79576d04ea723054294230 100644 (file)
@@ -11,6 +11,16 @@ import (
        "cmd/internal/src"
 )
 
+func haveRType(n, rtype ir.Node, fieldName string, required bool) bool {
+       if rtype != nil {
+               return true
+       }
+       if base.Debug.Unified != 0 && required {
+               base.FatalfAt(n.Pos(), "missing %s: %+v", fieldName, n)
+       }
+       return false
+}
+
 // assertOp asserts that n is an op.
 func assertOp(n ir.Node, op ir.Op) {
        base.AssertfAt(n.Op() == op, n.Pos(), "want %v, have %v", op, n)
@@ -61,6 +71,9 @@ func concreteRType(pos src.XPos, typ *types.Type) ir.Node {
 // representing the result slice type's element type.
 func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node {
        assertOp(n, ir.OAPPEND)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return sliceElemRType(pos, n.Type())
 }
 
@@ -71,6 +84,9 @@ func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node {
 func CompareRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
        assertOp2(n, ir.OEQ, ir.ONE)
        base.AssertfAt(n.X.Type().IsInterface() != n.Y.Type().IsInterface(), n.Pos(), "expect mixed interface and non-interface, have %L and %L", n.X, n.Y)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        typ := n.X.Type()
        if typ.IsInterface() {
                typ = n.Y.Type()
@@ -89,6 +105,9 @@ func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node {
        assertOp(n, ir.OCONVIFACE)
        src, dst := n.X.Type(), n.Type()
        base.AssertfAt(dst.IsInterface(), n.Pos(), "want interface type, have %L", n)
+       if haveRType(n, n.TypeWord, "TypeWord", false) {
+               return n.TypeWord
+       }
        if dst.IsEmptyInterface() {
                return concreteRType(pos, src) // direct eface construction
        }
@@ -98,12 +117,15 @@ func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node {
        return TypePtrAt(pos, dst) // convI2I
 }
 
-// ConvIfaceDataWordRType asserts that n is a conversion from
+// ConvIfaceSrcRType asserts that n is a conversion from
 // non-interface type to interface type (or OCONVIDATA operation), and
 // returns an expression that yields the *runtime._type for copying
 // the convertee value to the heap.
-func ConvIfaceDataWordRType(pos src.XPos, n *ir.ConvExpr) ir.Node {
+func ConvIfaceSrcRType(pos src.XPos, n *ir.ConvExpr) ir.Node {
        assertOp2(n, ir.OCONVIFACE, ir.OCONVIDATA)
+       if haveRType(n, n.SrcRType, "SrcRType", false) {
+               return n.SrcRType
+       }
        return concreteRType(pos, n.X.Type())
 }
 
@@ -112,6 +134,9 @@ func ConvIfaceDataWordRType(pos src.XPos, n *ir.ConvExpr) ir.Node {
 // destination slice type's element type.
 func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
        assertOp(n, ir.OCOPY)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return sliceElemRType(pos, n.X.Type())
 }
 
@@ -120,6 +145,9 @@ func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
 // map type.
 func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
        assertOp(n, ir.ODELETE)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return mapRType(pos, n.Args[0].Type())
 }
 
@@ -128,6 +156,9 @@ func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
 // map type.
 func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node {
        assertOp(n, ir.OINDEXMAP)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return mapRType(pos, n.X.Type())
 }
 
@@ -136,6 +167,9 @@ func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node {
 // value representing that channel type.
 func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
        assertOp(n, ir.OMAKECHAN)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return chanRType(pos, n.Type())
 }
 
@@ -144,6 +178,9 @@ func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
 // representing that map type.
 func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
        assertOp(n, ir.OMAKEMAP)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return mapRType(pos, n.Type())
 }
 
@@ -152,6 +189,9 @@ func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
 // value representing that slice type's element type.
 func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
        assertOp2(n, ir.OMAKESLICE, ir.OMAKESLICECOPY)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return sliceElemRType(pos, n.Type())
 }
 
@@ -160,6 +200,9 @@ func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
 // representing that map type.
 func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node {
        assertOp(n, ir.ORANGE)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return mapRType(pos, n.X.Type())
 }
 
@@ -168,5 +211,8 @@ func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node {
 // representing the result slice type's element type.
 func UnsafeSliceElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
        assertOp(n, ir.OUNSAFESLICE)
+       if haveRType(n, n.RType, "RType", false) {
+               return n.RType
+       }
        return sliceElemRType(pos, n.Type())
 }
index e857f325ec8bfa0fc6ac78762a7b38c7fc31bc42..753dbc3e887c0c41834f506f52f954e378c7660c 100644 (file)
@@ -170,7 +170,7 @@ func dataWord(conv *ir.ConvExpr, init *ir.Nodes) ir.Node {
                        n = copyExpr(n, fromType, init)
                }
                fn = typecheck.SubstArgTypes(fn, fromType)
-               args = []ir.Node{reflectdata.ConvIfaceDataWordRType(base.Pos, conv), typecheck.NodAddr(n)}
+               args = []ir.Node{reflectdata.ConvIfaceSrcRType(base.Pos, conv), typecheck.NodAddr(n)}
        } else {
                // Use a specialized conversion routine that takes the type being
                // converted by value, not by pointer.