aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2023-11-06 16:28:25 -0500
committerMichael Pratt <mpratt@google.com>2023-11-13 18:17:57 +0000
commit42bd21be1cf54876ce24c489852721049ef293e2 (patch)
tree448a827e75e06d9fc2bbfdf31de73176d6e42af5 /src/cmd/compile/internal/noder
parentfb6ff1e4caaece9be61c45518ffb51081e892a73 (diff)
downloadgo-42bd21be1cf54876ce24c489852721049ef293e2.tar.xz
cmd/compile: support lookup of functions from export data
As of CL 539699, PGO-based devirtualization supports devirtualization of function values in addition to interface method calls. As with CL 497175, we need to explicitly look up functions from export data that may not be imported already. Symbol naming is ambiguous (`foo.Bar.func1` could be a closure or a method), so we simply attempt to do both types of lookup. That said, closures are defined in export data only as OCLOSURE nodes in the enclosing function, which this CL does not yet attempt to expand. For #61577. Change-Id: Ic7205b046218a4dfb8c4162ece3620ed1c3cb40a Reviewed-on: https://go-review.googlesource.com/c/go/+/540258 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder')
-rw-r--r--src/cmd/compile/internal/noder/unified.go45
1 files changed, 41 insertions, 4 deletions
diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go
index 5948cac58c..a803e53502 100644
--- a/src/cmd/compile/internal/noder/unified.go
+++ b/src/cmd/compile/internal/noder/unified.go
@@ -30,8 +30,8 @@ var localPkgReader *pkgReader
// LookupMethodFunc returns the ir.Func for an arbitrary full symbol name if
// that function exists in the set of available export data.
//
-// This allows lookup of arbitrary methods that aren't otherwise referenced by
-// the local package and thus haven't been read yet.
+// This allows lookup of arbitrary functions and methods that aren't otherwise
+// referenced by the local package and thus haven't been read yet.
//
// TODO(prattmic): Does not handle instantiation of generic types. Currently
// profiles don't contain the original type arguments, so we won't be able to
@@ -40,7 +40,7 @@ var localPkgReader *pkgReader
// TODO(prattmic): Hit rate of this function is usually fairly low, and errors
// are only used when debug logging is enabled. Consider constructing cheaper
// errors by default.
-func LookupMethodFunc(fullName string) (*ir.Func, error) {
+func LookupFunc(fullName string) (*ir.Func, error) {
pkgPath, symName, err := ir.ParseLinkFuncName(fullName)
if err != nil {
return nil, fmt.Errorf("error parsing symbol name %q: %v", fullName, err)
@@ -51,6 +51,43 @@ func LookupMethodFunc(fullName string) (*ir.Func, error) {
return nil, fmt.Errorf("pkg %s doesn't exist in %v", pkgPath, types.PkgMap())
}
+ // Symbol naming is ambiguous. We can't necessarily distinguish between
+ // a method and a closure. e.g., is foo.Bar.func1 a closure defined in
+ // function Bar, or a method on type Bar? Thus we must simply attempt
+ // to lookup both.
+
+ fn, err := lookupFunction(pkg, symName)
+ if err == nil {
+ return fn, nil
+ }
+
+ fn, mErr := lookupMethod(pkg, symName)
+ if mErr == nil {
+ return fn, nil
+ }
+
+ return nil, fmt.Errorf("%s is not a function (%v) or method (%v)", fullName, err, mErr)
+}
+
+func lookupFunction(pkg *types.Pkg, symName string) (*ir.Func, error) {
+ sym := pkg.Lookup(symName)
+
+ // TODO(prattmic): Enclosed functions (e.g., foo.Bar.func1) are not
+ // present in objReader, only as OCLOSURE nodes in the enclosing
+ // function.
+ pri, ok := objReader[sym]
+ if !ok {
+ return nil, fmt.Errorf("func sym %v missing objReader", sym)
+ }
+
+ name := pri.pr.objIdx(pri.idx, nil, nil, false).(*ir.Name)
+ if name.Op() != ir.ONAME || name.Class != ir.PFUNC {
+ return nil, fmt.Errorf("func sym %v refers to non-function name: %v", sym, name)
+ }
+ return name.Func, nil
+}
+
+func lookupMethod(pkg *types.Pkg, symName string) (*ir.Func, error) {
// N.B. readPackage creates a Sym for every object in the package to
// initialize objReader and importBodyReader, even if the object isn't
// read.
@@ -130,7 +167,7 @@ func LookupMethodFunc(fullName string) (*ir.Func, error) {
func unified(m posMap, noders []*noder) {
inline.InlineCall = unifiedInlineCall
typecheck.HaveInlineBody = unifiedHaveInlineBody
- pgo.LookupMethodFunc = LookupMethodFunc
+ pgo.LookupFunc = LookupFunc
data := writePkgStub(m, noders)