case OCONVIFACE:
n.Left = walkexpr(n.Left, init)
- // Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped.
- if isdirectiface(n.Left.Type) {
- var t *Node
- if n.Type.IsEmptyInterface() {
- t = typename(n.Left.Type)
- } else {
- t = itabname(n.Left.Type, n.Type)
+ fromType := n.Left.Type
+ toType := n.Type
+
+ // typeword generates the type word of the interface value.
+ typeword := func() *Node {
+ if toType.IsEmptyInterface() {
+ return typename(fromType)
}
- l := nod(OEFACE, t, n.Left)
- l.Type = n.Type
+ return itabname(fromType, toType)
+ }
+
+ // Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped.
+ if isdirectiface(fromType) {
+ l := nod(OEFACE, typeword(), n.Left)
+ l.Type = toType
l.SetTypecheck(n.Typecheck())
n = l
break
// or creating one on the stack.
var value *Node
switch {
- case n.Left.Type.Size() == 0:
+ case fromType.Size() == 0:
// n.Left is zero-sized. Use zerobase.
cheapexpr(n.Left, init) // Evaluate n.Left for side-effects. See issue 19246.
value = zerobase
- case n.Left.Type.IsBoolean() || (n.Left.Type.Size() == 1 && n.Left.Type.IsInteger()):
+ case fromType.IsBoolean() || (fromType.Size() == 1 && fromType.IsInteger()):
// n.Left is a bool/byte. Use staticbytes[n.Left].
n.Left = cheapexpr(n.Left, init)
value = nod(OINDEX, staticbytes, byteindex(n.Left))
case n.Left.Class() == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly():
// n.Left is a readonly global; use it directly.
value = n.Left
- case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024:
+ case !fromType.IsInterface() && n.Esc == EscNone && fromType.Width <= 1024:
// n.Left does not escape. Use a stack temporary initialized to n.Left.
- value = temp(n.Left.Type)
+ value = temp(fromType)
init.Append(typecheck(nod(OAS, value, n.Left), Etop))
}
if value != nil {
// Value is identical to n.Left.
// Construct the interface directly: {type/itab, &value}.
- var t *Node
- if n.Type.IsEmptyInterface() {
- t = typename(n.Left.Type)
- } else {
- t = itabname(n.Left.Type, n.Type)
- }
- l := nod(OEFACE, t, typecheck(nod(OADDR, value, nil), Erv))
- l.Type = n.Type
+ l := nod(OEFACE, typeword(), typecheck(nod(OADDR, value, nil), Erv))
+ l.Type = toType
l.SetTypecheck(n.Typecheck())
n = l
break
// tmp = tmp.type
// }
// e = iface{tmp, i.data}
- if n.Type.IsEmptyInterface() && n.Left.Type.IsInterface() && !n.Left.Type.IsEmptyInterface() {
+ if toType.IsEmptyInterface() && fromType.IsInterface() && !fromType.IsEmptyInterface() {
// Evaluate the input interface.
- c := temp(n.Left.Type)
+ c := temp(fromType)
init.Append(nod(OAS, c, n.Left))
// Get the itab out of the interface.
// Build the result.
e := nod(OEFACE, tmp, ifaceData(c, types.NewPtr(types.Types[TUINT8])))
- e.Type = n.Type // assign type manually, typecheck doesn't understand OEFACE.
+ e.Type = toType // assign type manually, typecheck doesn't understand OEFACE.
e.SetTypecheck(1)
n = e
break
}
- fnname, needsaddr := convFuncName(n.Left.Type, n.Type)
+ fnname, needsaddr := convFuncName(fromType, toType)
- if !needsaddr && !n.Left.Type.IsInterface() {
+ if !needsaddr && !fromType.IsInterface() {
// Use a specialized conversion routine that only returns a data pointer.
// ptr = convT2X(val)
// e = iface{typ/tab, ptr}
fn := syslook(fnname)
- dowidth(n.Left.Type)
- fn = substArgTypes(fn, n.Left.Type)
+ dowidth(fromType)
+ fn = substArgTypes(fn, fromType)
dowidth(fn.Type)
call := nod(OCALL, fn, nil)
call.List.Set1(n.Left)
call = typecheck(call, Erv)
call = walkexpr(call, init)
call = safeexpr(call, init)
- var tab *Node
- if n.Type.IsEmptyInterface() {
- tab = typename(n.Left.Type)
- } else {
- tab = itabname(n.Left.Type, n.Type)
- }
- e := nod(OEFACE, tab, call)
- e.Type = n.Type
+ e := nod(OEFACE, typeword(), call)
+ e.Type = toType
e.SetTypecheck(1)
n = e
break
}
- var ll []*Node
- if n.Type.IsEmptyInterface() {
- if !n.Left.Type.IsInterface() {
- ll = append(ll, typename(n.Left.Type))
- }
+ var tab *Node
+ if fromType.IsInterface() {
+ // convI2I
+ tab = typename(toType)
} else {
- if n.Left.Type.IsInterface() {
- ll = append(ll, typename(n.Type))
- } else {
- ll = append(ll, itabname(n.Left.Type, n.Type))
- }
+ // convT2x
+ tab = typeword()
}
v := n.Left
}
v = nod(OADDR, v, nil)
}
- ll = append(ll, v)
- dowidth(n.Left.Type)
+ dowidth(fromType)
fn := syslook(fnname)
- fn = substArgTypes(fn, n.Left.Type, n.Type)
+ fn = substArgTypes(fn, fromType, toType)
dowidth(fn.Type)
n = nod(OCALL, fn, nil)
- n.List.Set(ll)
+ n.List.Set2(tab, v)
n = typecheck(n, Erv)
n = walkexpr(n, init)