]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: new devirtualization pkg [generated]
authorMatthew Dempsky <mdempsky@google.com>
Thu, 24 Dec 2020 23:42:37 +0000 (15:42 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 25 Dec 2020 00:39:24 +0000 (00:39 +0000)
The devirtualization code was only in inl.go because it reused some of
the same helper functions as inlining (notably staticValue), but that
code all ended up in package ir instead anyway. Beyond that minor
commonality, it's entirely separate from inlining.

It's definitely on the small side, but consistent with the new
micropass-as-a-package approach we're trying.

[git-generate]
cd src/cmd/compile/internal/inline
rf '
  mv Devirtualize Func
  mv devirtualizeCall Call
  mv Func Call devirtualize.go
  mv devirtualize.go cmd/compile/internal/devirtualize
'

Change-Id: Iff7b9fe486856660a8107d5391c54b7e8d238706
Reviewed-on: https://go-review.googlesource.com/c/go/+/280212
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/devirtualize/devirtualize.go [new file with mode: 0644]
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/inline/inl.go

diff --git a/src/cmd/compile/internal/devirtualize/devirtualize.go b/src/cmd/compile/internal/devirtualize/devirtualize.go
new file mode 100644 (file)
index 0000000..95b28ef
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// The inlining facility makes 2 passes: first caninl determines which
+// functions are suitable for inlining, and for those that are it
+// saves a copy of the body. Then inlcalls walks each function body to
+// expand calls to inlinable functions.
+//
+// The Debug.l flag controls the aggressiveness. Note that main() swaps level 0 and 1,
+// making 1 the default and -l disable. Additional levels (beyond -l) may be buggy and
+// are not supported.
+//      0: disabled
+//      1: 80-nodes leaf functions, oneliners, panic, lazy typechecking (default)
+//      2: (unassigned)
+//      3: (unassigned)
+//      4: allow non-leaf functions
+//
+// At some point this may get another default and become switch-offable with -N.
+//
+// The -d typcheckinl flag enables early typechecking of all imported bodies,
+// which is useful to flush out bugs.
+//
+// The Debug.m flag enables diagnostic output.  a single -m is useful for verifying
+// which calls get inlined or not, more is for debugging, and may go away at any point.
+
+package devirtualize
+
+import (
+       "cmd/compile/internal/base"
+       "cmd/compile/internal/ir"
+       "cmd/compile/internal/typecheck"
+       "cmd/compile/internal/types"
+)
+
+// Devirtualize replaces interface method calls within fn with direct
+// concrete-type method calls where applicable.
+func Func(fn *ir.Func) {
+       ir.CurFunc = fn
+       ir.VisitList(fn.Body, func(n ir.Node) {
+               if n.Op() == ir.OCALLINTER {
+                       Call(n.(*ir.CallExpr))
+               }
+       })
+}
+
+func Call(call *ir.CallExpr) {
+       sel := call.X.(*ir.SelectorExpr)
+       r := ir.StaticValue(sel.X)
+       if r.Op() != ir.OCONVIFACE {
+               return
+       }
+       recv := r.(*ir.ConvExpr)
+
+       typ := recv.X.Type()
+       if typ.IsInterface() {
+               return
+       }
+
+       dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil)
+       dt.SetType(typ)
+       x := typecheck.Callee(ir.NewSelectorExpr(sel.Pos(), ir.OXDOT, dt, sel.Sel))
+       switch x.Op() {
+       case ir.ODOTMETH:
+               x := x.(*ir.SelectorExpr)
+               if base.Flag.LowerM != 0 {
+                       base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ)
+               }
+               call.SetOp(ir.OCALLMETH)
+               call.X = x
+       case ir.ODOTINTER:
+               // Promoted method from embedded interface-typed field (#42279).
+               x := x.(*ir.SelectorExpr)
+               if base.Flag.LowerM != 0 {
+                       base.WarnfAt(call.Pos(), "partially devirtualizing %v to %v", sel, typ)
+               }
+               call.SetOp(ir.OCALLINTER)
+               call.X = x
+       default:
+               // TODO(mdempsky): Turn back into Fatalf after more testing.
+               if base.Flag.LowerM != 0 {
+                       base.WarnfAt(call.Pos(), "failed to devirtualize %v (%v)", x, x.Op())
+               }
+               return
+       }
+
+       // Duplicated logic from typecheck for function call return
+       // value types.
+       //
+       // Receiver parameter size may have changed; need to update
+       // call.Type to get correct stack offsets for result
+       // parameters.
+       types.CheckSize(x.Type())
+       switch ft := x.Type(); ft.NumResults() {
+       case 0:
+       case 1:
+               call.SetType(ft.Results().Field(0).Type)
+       default:
+               call.SetType(ft.Results())
+       }
+}
index 8483c87a38d1061f7a409236f2399ed43ce1a483..ba3620e6769fdadd1ad63a9894b0c40a96d0918e 100644 (file)
@@ -10,6 +10,7 @@ import (
        "bufio"
        "bytes"
        "cmd/compile/internal/base"
+       "cmd/compile/internal/devirtualize"
        "cmd/compile/internal/dwarfgen"
        "cmd/compile/internal/escape"
        "cmd/compile/internal/inline"
@@ -237,7 +238,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
        // Devirtualize.
        for _, n := range typecheck.Target.Decls {
                if n.Op() == ir.ODCLFUNC {
-                       inline.Devirtualize(n.(*ir.Func))
+                       devirtualize.Func(n.(*ir.Func))
                }
        }
        ir.CurFunc = nil
index 222e62d0cc89408ac68d464da4324b65ac518cf9..9ffb08048a6f6806d3ac3f8db908adfc9ce4c5e6 100644 (file)
@@ -1203,73 +1203,6 @@ func pruneUnusedAutos(ll []*ir.Name, vis *hairyVisitor) []*ir.Name {
        return s
 }
 
-// Devirtualize replaces interface method calls within fn with direct
-// concrete-type method calls where applicable.
-func Devirtualize(fn *ir.Func) {
-       ir.CurFunc = fn
-       ir.VisitList(fn.Body, func(n ir.Node) {
-               if n.Op() == ir.OCALLINTER {
-                       devirtualizeCall(n.(*ir.CallExpr))
-               }
-       })
-}
-
-func devirtualizeCall(call *ir.CallExpr) {
-       sel := call.X.(*ir.SelectorExpr)
-       r := ir.StaticValue(sel.X)
-       if r.Op() != ir.OCONVIFACE {
-               return
-       }
-       recv := r.(*ir.ConvExpr)
-
-       typ := recv.X.Type()
-       if typ.IsInterface() {
-               return
-       }
-
-       dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil)
-       dt.SetType(typ)
-       x := typecheck.Callee(ir.NewSelectorExpr(sel.Pos(), ir.OXDOT, dt, sel.Sel))
-       switch x.Op() {
-       case ir.ODOTMETH:
-               x := x.(*ir.SelectorExpr)
-               if base.Flag.LowerM != 0 {
-                       base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ)
-               }
-               call.SetOp(ir.OCALLMETH)
-               call.X = x
-       case ir.ODOTINTER:
-               // Promoted method from embedded interface-typed field (#42279).
-               x := x.(*ir.SelectorExpr)
-               if base.Flag.LowerM != 0 {
-                       base.WarnfAt(call.Pos(), "partially devirtualizing %v to %v", sel, typ)
-               }
-               call.SetOp(ir.OCALLINTER)
-               call.X = x
-       default:
-               // TODO(mdempsky): Turn back into Fatalf after more testing.
-               if base.Flag.LowerM != 0 {
-                       base.WarnfAt(call.Pos(), "failed to devirtualize %v (%v)", x, x.Op())
-               }
-               return
-       }
-
-       // Duplicated logic from typecheck for function call return
-       // value types.
-       //
-       // Receiver parameter size may have changed; need to update
-       // call.Type to get correct stack offsets for result
-       // parameters.
-       types.CheckSize(x.Type())
-       switch ft := x.Type(); ft.NumResults() {
-       case 0:
-       case 1:
-               call.SetType(ft.Results().Field(0).Type)
-       default:
-               call.SetType(ft.Results())
-       }
-}
-
 // numNonClosures returns the number of functions in list which are not closures.
 func numNonClosures(list []*ir.Func) int {
        count := 0