diff options
| author | Michael Pratt <mpratt@google.com> | 2024-02-08 13:07:33 -0500 |
|---|---|---|
| committer | Michael Pratt <mpratt@google.com> | 2024-02-09 20:03:18 +0000 |
| commit | 532c6f1c8d724975f578c8ec519f1f5b07d949da (patch) | |
| tree | c38b431b178c8b34fc39188ffc4a0b97f0fa87e5 /src/cmd/compile/internal/noder/reader.go | |
| parent | d94ab597af9b3f8e8ba371023314d80f6b3be5a5 (diff) | |
| download | go-532c6f1c8d724975f578c8ec519f1f5b07d949da.tar.xz | |
cmd/compile: fail noder.LookupFunc gracefully if function generic
PGO uses noder.LookupFunc to look for devirtualization targets in
export data. LookupFunc does not support type-parameterized
functions, and will currently fail the build when attempting to lookup
a type-parameterized function because objIdx is passed the wrong
number of type arguments.
This doesn't usually come up, as a PGO profile will report a generic
function with a symbol name like Func[.go.shape.foo]. In export data,
this is just Func, so when we do LookupFunc("Func[.go.shape.foo]")
lookup simply fails because the name doesn't exist.
However, if Func is not generic when the profile is collected, but the
source has since changed to make Func generic, then LookupFunc("Func")
will find the object successfully, only to fail the build because we
failed to provide type arguments.
Handle this with a objIdxMayFail, which allows graceful failure if the
object requires type arguments.
Bumping the language version to 1.21 in pgo_devirtualize_test.go is
required for type inference of the uses of mult.MultFn in
cmd/compile/internal/test/testdata/pgo/devirtualize/devirt_test.go.
Fixes #65615.
Change-Id: I84d9344840b851182f5321b8f7a29a591221b29f
Reviewed-on: https://go-review.googlesource.com/c/go/+/562737
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/compile/internal/noder/reader.go')
| -rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index f5d1fce50c..2dddd20165 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -663,9 +663,24 @@ func (pr *pkgReader) objInstIdx(info objInfo, dict *readerDict, shaped bool) ir. } // objIdx returns the specified object, instantiated with the given -// type arguments, if any. If shaped is true, then the shaped variant -// of the object is returned instead. +// type arguments, if any. +// If shaped is true, then the shaped variant of the object is returned +// instead. func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) ir.Node { + n, err := pr.objIdxMayFail(idx, implicits, explicits, shaped) + if err != nil { + base.Fatalf("%v", err) + } + return n +} + +// objIdxMayFail is equivalent to objIdx, but returns an error rather than +// failing the build if this object requires type arguments and the incorrect +// number of type arguments were passed. +// +// Other sources of internal failure (such as duplicate definitions) still fail +// the build. +func (pr *pkgReader) objIdxMayFail(idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) (ir.Node, error) { rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) _, sym := rname.qualifiedIdent() tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) @@ -674,22 +689,25 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Typ assert(!sym.IsBlank()) switch sym.Pkg { case types.BuiltinPkg, types.UnsafePkg: - return sym.Def.(ir.Node) + return sym.Def.(ir.Node), nil } if pri, ok := objReader[sym]; ok { - return pri.pr.objIdx(pri.idx, nil, explicits, shaped) + return pri.pr.objIdxMayFail(pri.idx, nil, explicits, shaped) } if sym.Pkg.Path == "runtime" { - return typecheck.LookupRuntime(sym.Name) + return typecheck.LookupRuntime(sym.Name), nil } base.Fatalf("unresolved stub: %v", sym) } - dict := pr.objDictIdx(sym, idx, implicits, explicits, shaped) + dict, err := pr.objDictIdx(sym, idx, implicits, explicits, shaped) + if err != nil { + return nil, err + } sym = dict.baseSym if !sym.IsBlank() && sym.Def != nil { - return sym.Def.(*ir.Name) + return sym.Def.(*ir.Name), nil } r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) @@ -725,7 +743,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Typ name := do(ir.OTYPE, false) setType(name, r.typ()) name.SetAlias(true) - return name + return name, nil case pkgbits.ObjConst: name := do(ir.OLITERAL, false) @@ -733,7 +751,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Typ val := FixValue(typ, r.Value()) setType(name, typ) setValue(name, val) - return name + return name, nil case pkgbits.ObjFunc: if sym.Name == "init" { @@ -768,7 +786,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Typ } rext.funcExt(name, nil) - return name + return name, nil case pkgbits.ObjType: name := do(ir.OTYPE, true) @@ -805,13 +823,13 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Typ r.needWrapper(typ) } - return name + return name, nil case pkgbits.ObjVar: name := do(ir.ONAME, false) setType(name, r.typ()) rext.varExt(name) - return name + return name, nil } } @@ -908,7 +926,7 @@ func shapify(targ *types.Type, basic bool) *types.Type { } // objDictIdx reads and returns the specified object dictionary. -func (pr *pkgReader) objDictIdx(sym *types.Sym, idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) *readerDict { +func (pr *pkgReader) objDictIdx(sym *types.Sym, idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) (*readerDict, error) { r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) dict := readerDict{ @@ -919,7 +937,7 @@ func (pr *pkgReader) objDictIdx(sym *types.Sym, idx pkgbits.Index, implicits, ex nexplicits := r.Len() if nimplicits > len(implicits) || nexplicits != len(explicits) { - base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits)) + return nil, fmt.Errorf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits)) } dict.targs = append(implicits[:nimplicits:nimplicits], explicits...) @@ -984,7 +1002,7 @@ func (pr *pkgReader) objDictIdx(sym *types.Sym, idx pkgbits.Index, implicits, ex dict.itabs[i] = itabInfo{typ: r.typInfo(), iface: r.typInfo()} } - return &dict + return &dict, nil } func (r *reader) typeParamNames() { @@ -2529,7 +2547,10 @@ func (pr *pkgReader) objDictName(idx pkgbits.Index, implicits, explicits []*type base.Fatalf("unresolved stub: %v", sym) } - dict := pr.objDictIdx(sym, idx, implicits, explicits, false) + dict, err := pr.objDictIdx(sym, idx, implicits, explicits, false) + if err != nil { + base.Fatalf("%v", err) + } return pr.dictNameOf(dict) } |
