mirror of
https://github.com/golang/go
synced 2024-11-23 04:20:03 -07:00
cmd/compile: simplify walk OCONVIFACE
n.Type and n.Left.Type are used heavily. Give them useful names. We generate the type word frequently. Make it a closure. (We don't want to generate it up front, since there are some code paths that don't need it, and generating it has side-effects.) Simplify and document the final call construction. Follow-up to address feedback on CL 147360. Change-Id: I251134a55cf80d8b1676280a345d150f2288c09a Reviewed-on: https://go-review.googlesource.com/c/147538 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Martin Möhrmann <moehrmann@google.com>
This commit is contained in:
parent
6dd70fc5e3
commit
fe2c588b1c
@ -815,16 +815,21 @@ opswitch:
|
||||
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
|
||||
@ -844,11 +849,11 @@ opswitch:
|
||||
// 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))
|
||||
@ -856,23 +861,17 @@ opswitch:
|
||||
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
|
||||
@ -884,9 +883,9 @@ opswitch:
|
||||
// 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.
|
||||
@ -900,51 +899,41 @@ opswitch:
|
||||
|
||||
// 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
|
||||
@ -960,14 +949,13 @@ opswitch:
|
||||
}
|
||||
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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user