]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: simplify walk OCONVIFACE
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 5 Nov 2018 23:42:14 +0000 (15:42 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Sat, 10 Nov 2018 13:39:01 +0000 (13:39 +0000)
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>
src/cmd/compile/internal/gc/walk.go

index fa0dcab5ebdee52cada8967ab108cd75af35a9ec..37d995b1bdf8cab872e172210eb97af0a041434b 100644 (file)
@@ -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)