mirror of
https://github.com/golang/go
synced 2024-09-04 15:34:21 +00:00
[dev.typeparams] cmd/compile: ensure methods of generic types survive linker pruning
Calling MarkTypeUsedInInterface before inlining is problematic (when using the containing function as the reference source), because we end up attaching a relocation to the original function, which is then deadcode removed because all instances of it were inlined. (All other current uses of MarkTypeUsedInInterface happen after inlining, so they don't have this problem.) Instead, attach the relocation to the dictionary in which the type appears. This should always work, because if the dictionary is ever deadcode eliminated, then the type can never be put in an interface, which means we indeed don't need its methods. This CL is a bit overkill, as not *all* types in the dictionary need this mark, but it is sufficient for now. Change-Id: I2d39456691f1c3df8efe3bddc3b9017e0ef37a7f Reviewed-on: https://go-review.googlesource.com/c/go/+/336012 Trust: Keith Randall <khr@golang.org> Trust: Dan Scales <danscales@google.com> Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
parent
73af5f718f
commit
2fe4b14795
|
@ -566,7 +566,6 @@ const UINTSTRING = "u8" // XX fix for 32-bit arch
|
|||
// buf. fieldSym is the sym of the field associated with type t, if it is in a
|
||||
// struct. fieldSym could be used to have special naming for blank fields, etc.
|
||||
func accumGcshape(fl []*types.Field, buf *bytes.Buffer, t *types.Type, fieldSym *types.Sym) []*types.Field {
|
||||
|
||||
// t.Kind() is already the kind of the underlying type, so no need to
|
||||
// reference t.Underlying() to reference the underlying type.
|
||||
assert(t.Kind() == t.Underlying().Kind())
|
||||
|
@ -1220,7 +1219,6 @@ func (subst *subster) node(n ir.Node) ir.Node {
|
|||
dst := subst.concretify.Typ(subst.shape2param[src].Bound())
|
||||
// Mark that we use the methods of this concrete type.
|
||||
// Otherwise the linker deadcode-eliminates them :(
|
||||
reflectdata.MarkTypeUsedInInterface(subst.unshapifyTyp(src), subst.newf.Sym().Linksym())
|
||||
ix := subst.findDictType(subst.shape2param[src])
|
||||
assert(ix >= 0)
|
||||
mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, dst, subst.shape2param[src], ix)
|
||||
|
@ -1566,6 +1564,11 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool)
|
|||
infoPrint(" * %v\n", t)
|
||||
s := reflectdata.TypeLinksym(t)
|
||||
off = objw.SymPtr(lsym, off, s, 0)
|
||||
// Ensure that methods on t don't get deadcode eliminated
|
||||
// by the linker.
|
||||
// TODO: This is somewhat overkill, we really only need it
|
||||
// for types that are put into interfaces.
|
||||
reflectdata.MarkTypeUsedInInterface(t, lsym)
|
||||
}
|
||||
subst := typecheck.Tsubster{
|
||||
Tparams: info.tparams,
|
||||
|
@ -1577,6 +1580,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool)
|
|||
infoPrint(" - %v\n", ts)
|
||||
s := reflectdata.TypeLinksym(ts)
|
||||
off = objw.SymPtr(lsym, off, s, 0)
|
||||
reflectdata.MarkTypeUsedInInterface(ts, lsym)
|
||||
}
|
||||
// Emit an entry for each subdictionary (after substituting targs)
|
||||
for _, n := range info.subDictCalls {
|
||||
|
|
Loading…
Reference in a new issue