// 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 {
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
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.
//
miniExpr
X Node
Index Node
+ RType Node `mknode:"-"` // see reflectdata/helpers.go
Assigned bool
}
// 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 {
// 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 {
"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)
// 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())
}
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()
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
}
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())
}
// 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())
}
// 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())
}
// 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())
}
// 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())
}
// 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())
}
// 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())
}
// 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())
}
// 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())
}