mirror of
https://github.com/golang/go
synced 2024-11-23 20:20:01 -07:00
[dev.unified] cmd/compile: add RType fields
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>
This commit is contained in:
parent
5e0258c700
commit
5960f4ec10
@ -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.
|
// or Op(X, Y) for builtin functions that do not become calls.
|
||||||
type BinaryExpr struct {
|
type BinaryExpr struct {
|
||||||
miniExpr
|
miniExpr
|
||||||
X Node
|
X Node
|
||||||
Y Node
|
Y Node
|
||||||
|
RType Node `mknode:"-"` // see reflectdata/helpers.go
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
|
func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
|
||||||
@ -148,6 +149,7 @@ type CallExpr struct {
|
|||||||
origNode
|
origNode
|
||||||
X Node
|
X Node
|
||||||
Args Nodes
|
Args Nodes
|
||||||
|
RType Node `mknode:"-"` // see reflectdata/helpers.go
|
||||||
KeepAlive []*Name // vars to be kept alive until call returns
|
KeepAlive []*Name // vars to be kept alive until call returns
|
||||||
IsDDD bool
|
IsDDD bool
|
||||||
NoInline bool
|
NoInline bool
|
||||||
@ -247,6 +249,17 @@ type ConvExpr struct {
|
|||||||
miniExpr
|
miniExpr
|
||||||
X Node
|
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
|
// For -d=checkptr instrumentation of conversions from
|
||||||
// unsafe.Pointer to *Elem or *[Len]Elem.
|
// unsafe.Pointer to *Elem or *[Len]Elem.
|
||||||
//
|
//
|
||||||
@ -285,6 +298,7 @@ type IndexExpr struct {
|
|||||||
miniExpr
|
miniExpr
|
||||||
X Node
|
X Node
|
||||||
Index Node
|
Index Node
|
||||||
|
RType Node `mknode:"-"` // see reflectdata/helpers.go
|
||||||
Assigned bool
|
Assigned bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,8 +409,9 @@ func (n *LogicalExpr) SetOp(op Op) {
|
|||||||
// but *not* OMAKE (that's a pre-typechecking CallExpr).
|
// but *not* OMAKE (that's a pre-typechecking CallExpr).
|
||||||
type MakeExpr struct {
|
type MakeExpr struct {
|
||||||
miniExpr
|
miniExpr
|
||||||
Len Node
|
RType Node `mknode:"-"` // see reflectdata/helpers.go
|
||||||
Cap Node
|
Len Node
|
||||||
|
Cap Node
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr {
|
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
|
// Runtime type information provided by walkDotType for
|
||||||
// assertions from non-empty interface to concrete type.
|
// 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 {
|
func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr {
|
||||||
|
@ -333,6 +333,7 @@ type RangeStmt struct {
|
|||||||
Label *types.Sym
|
Label *types.Sym
|
||||||
Def bool
|
Def bool
|
||||||
X Node
|
X Node
|
||||||
|
RType Node `mknode:"-"` // see reflectdata/helpers.go
|
||||||
Key Node
|
Key Node
|
||||||
Value Node
|
Value Node
|
||||||
Body Nodes
|
Body Nodes
|
||||||
|
@ -11,6 +11,16 @@ import (
|
|||||||
"cmd/internal/src"
|
"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.
|
// assertOp asserts that n is an op.
|
||||||
func assertOp(n ir.Node, op ir.Op) {
|
func assertOp(n ir.Node, op ir.Op) {
|
||||||
base.AssertfAt(n.Op() == op, n.Pos(), "want %v, have %v", op, n)
|
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.
|
// representing the result slice type's element type.
|
||||||
func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node {
|
func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node {
|
||||||
assertOp(n, ir.OAPPEND)
|
assertOp(n, ir.OAPPEND)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return sliceElemRType(pos, n.Type())
|
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 {
|
func CompareRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
|
||||||
assertOp2(n, ir.OEQ, ir.ONE)
|
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)
|
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()
|
typ := n.X.Type()
|
||||||
if typ.IsInterface() {
|
if typ.IsInterface() {
|
||||||
typ = n.Y.Type()
|
typ = n.Y.Type()
|
||||||
@ -89,6 +105,9 @@ func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node {
|
|||||||
assertOp(n, ir.OCONVIFACE)
|
assertOp(n, ir.OCONVIFACE)
|
||||||
src, dst := n.X.Type(), n.Type()
|
src, dst := n.X.Type(), n.Type()
|
||||||
base.AssertfAt(dst.IsInterface(), n.Pos(), "want interface type, have %L", n)
|
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() {
|
if dst.IsEmptyInterface() {
|
||||||
return concreteRType(pos, src) // direct eface construction
|
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
|
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
|
// non-interface type to interface type (or OCONVIDATA operation), and
|
||||||
// returns an expression that yields the *runtime._type for copying
|
// returns an expression that yields the *runtime._type for copying
|
||||||
// the convertee value to the heap.
|
// 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)
|
assertOp2(n, ir.OCONVIFACE, ir.OCONVIDATA)
|
||||||
|
if haveRType(n, n.SrcRType, "SrcRType", false) {
|
||||||
|
return n.SrcRType
|
||||||
|
}
|
||||||
return concreteRType(pos, n.X.Type())
|
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.
|
// destination slice type's element type.
|
||||||
func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
|
func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
|
||||||
assertOp(n, ir.OCOPY)
|
assertOp(n, ir.OCOPY)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return sliceElemRType(pos, n.X.Type())
|
return sliceElemRType(pos, n.X.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +145,9 @@ func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
|
|||||||
// map type.
|
// map type.
|
||||||
func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
|
func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
|
||||||
assertOp(n, ir.ODELETE)
|
assertOp(n, ir.ODELETE)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return mapRType(pos, n.Args[0].Type())
|
return mapRType(pos, n.Args[0].Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +156,9 @@ func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
|
|||||||
// map type.
|
// map type.
|
||||||
func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node {
|
func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node {
|
||||||
assertOp(n, ir.OINDEXMAP)
|
assertOp(n, ir.OINDEXMAP)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return mapRType(pos, n.X.Type())
|
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.
|
// value representing that channel type.
|
||||||
func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
||||||
assertOp(n, ir.OMAKECHAN)
|
assertOp(n, ir.OMAKECHAN)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return chanRType(pos, n.Type())
|
return chanRType(pos, n.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +178,9 @@ func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
|||||||
// representing that map type.
|
// representing that map type.
|
||||||
func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
||||||
assertOp(n, ir.OMAKEMAP)
|
assertOp(n, ir.OMAKEMAP)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return mapRType(pos, n.Type())
|
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.
|
// value representing that slice type's element type.
|
||||||
func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
||||||
assertOp2(n, ir.OMAKESLICE, ir.OMAKESLICECOPY)
|
assertOp2(n, ir.OMAKESLICE, ir.OMAKESLICECOPY)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return sliceElemRType(pos, n.Type())
|
return sliceElemRType(pos, n.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +200,9 @@ func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
|
|||||||
// representing that map type.
|
// representing that map type.
|
||||||
func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node {
|
func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node {
|
||||||
assertOp(n, ir.ORANGE)
|
assertOp(n, ir.ORANGE)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return mapRType(pos, n.X.Type())
|
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.
|
// representing the result slice type's element type.
|
||||||
func UnsafeSliceElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
|
func UnsafeSliceElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
|
||||||
assertOp(n, ir.OUNSAFESLICE)
|
assertOp(n, ir.OUNSAFESLICE)
|
||||||
|
if haveRType(n, n.RType, "RType", false) {
|
||||||
|
return n.RType
|
||||||
|
}
|
||||||
return sliceElemRType(pos, n.Type())
|
return sliceElemRType(pos, n.Type())
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ func dataWord(conv *ir.ConvExpr, init *ir.Nodes) ir.Node {
|
|||||||
n = copyExpr(n, fromType, init)
|
n = copyExpr(n, fromType, init)
|
||||||
}
|
}
|
||||||
fn = typecheck.SubstArgTypes(fn, fromType)
|
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 {
|
} else {
|
||||||
// Use a specialized conversion routine that takes the type being
|
// Use a specialized conversion routine that takes the type being
|
||||||
// converted by value, not by pointer.
|
// converted by value, not by pointer.
|
||||||
|
Loading…
Reference in New Issue
Block a user