aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-07-23 17:19:51 -0700
committerDan Scales <danscales@google.com>2021-07-24 17:47:08 +0000
commit3dc0a0a2c5a7d8959a43265d4f73d7e2e509de5e (patch)
tree9aa4d3653e2a2ba3079cf3104ac4a58911e43447 /src/cmd/compile/internal
parent77e0bf294cc431d5608c183d56b6aadbb95b09b0 (diff)
downloadgo-3dc0a0a2c5a7d8959a43265d4f73d7e2e509de5e.tar.gz
go-3dc0a0a2c5a7d8959a43265d4f73d7e2e509de5e.zip
[dev.typeparams] cmd/compile: get rid of concretify use for bounds.
We just need to substitute from the typeparams to the shapes for the dst type of the bound. Removed concretify substituter, not used anymore. Also removed shape2params, not needed anymore. However, since the dst type is now not concrete, this gives more cases where the linker can't find a method. I realized that we need to call MarkUsedIfaceMethod to mark a method as used on a particular interface, else a type's method can be still deadcoded even though MarkTypeUsedInInterface has been called on the concrete type. I added a new version MarkUsedIfaceMethodIndex to fit my use case. Change-Id: Id67b72b350889dd3688b42739c337d5d79a0d1a2 Reviewed-on: https://go-review.googlesource.com/c/go/+/337230 Trust: Dan Scales <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal')
-rw-r--r--src/cmd/compile/internal/noder/stencil.go36
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go12
2 files changed, 28 insertions, 20 deletions
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index e308dd7a05..f1de1152c5 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -855,13 +855,9 @@ type subster struct {
ts typecheck.Tsubster
info *instInfo // Place to put extra info in the instantiation
- // Which type parameter the shape type came from.
- shape2param map[*types.Type]*types.Type
-
// unshapeify maps from shape types to the concrete types they represent.
// TODO: remove when we no longer need it.
- unshapify typecheck.Tsubster
- concretify typecheck.Tsubster
+ unshapify typecheck.Tsubster
// TODO: some sort of map from <shape type, interface type> to index in the
// dictionary where a *runtime.itab for the corresponding <concrete type,
@@ -920,23 +916,11 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
Targs: shapes,
Vars: make(map[*ir.Name]*ir.Name),
},
- shape2param: map[*types.Type]*types.Type{},
unshapify: typecheck.Tsubster{
Tparams: shapes,
Targs: targs,
Vars: make(map[*ir.Name]*ir.Name),
},
- concretify: typecheck.Tsubster{
- Tparams: tparams,
- Targs: targs,
- Vars: make(map[*ir.Name]*ir.Name),
- },
- }
- for i := range shapes {
- if !shapes[i].IsShape() {
- panic("must be a shape type")
- }
- subst.shape2param[shapes[i]] = tparams[i]
}
newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1)
@@ -992,7 +976,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
// g.instTypeList.
g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...)
g.instTypeList = append(g.instTypeList, subst.unshapify.InstTypeList...)
- g.instTypeList = append(g.instTypeList, subst.concretify.InstTypeList...)
if doubleCheck {
okConvs := map[ir.Node]bool{}
@@ -1258,7 +1241,10 @@ func (subst *subster) node(n ir.Node) ir.Node {
// 1) convert x to the bound interface
// 2) call M on that interface
gsrc := x.(*ir.SelectorExpr).X.Type()
- dst := subst.concretify.Typ(gsrc.Bound())
+ dst := gsrc.Bound()
+ if dst.HasTParam() {
+ dst = subst.ts.Typ(dst)
+ }
mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, x, dst, gsrc)
}
}
@@ -1714,6 +1700,18 @@ func (g *irgen) finalizeSyms() {
se := n.(*ir.SelectorExpr)
srctype = subst.Typ(se.X.Type())
dsttype = subst.Typ(se.X.Type().Bound())
+ found := false
+ for i, m := range dsttype.AllMethods().Slice() {
+ if se.Sel == m.Sym {
+ // Mark that this method se.Sel is
+ // used for the dsttype interface, so
+ // it won't get deadcoded.
+ reflectdata.MarkUsedIfaceMethodIndex(lsym, dsttype, i)
+ found = true
+ break
+ }
+ }
+ assert(found)
} else {
assert(n.Op() == ir.OCONVIFACE)
srctype = subst.Typ(n.(*ir.ConvExpr).X.Type())
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index 7eba5fb41e..3bf248a7ad 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -2006,13 +2006,23 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) {
tsym := TypeLinksym(ityp)
r := obj.Addrel(ir.CurFunc.LSym)
r.Sym = tsym
- // dot.Xoffset is the method index * PtrSize (the offset of code pointer
+ // dot.Offset() is the method index * PtrSize (the offset of code pointer
// in itab).
midx := dot.Offset() / int64(types.PtrSize)
r.Add = InterfaceMethodOffset(ityp, midx)
r.Type = objabi.R_USEIFACEMETHOD
}
+// MarkUsedIfaceMethodIndex marks that that method number ix (in the AllMethods list)
+// of interface type ityp is used, and should be attached to lsym.
+func MarkUsedIfaceMethodIndex(lsym *obj.LSym, ityp *types.Type, ix int) {
+ tsym := TypeLinksym(ityp)
+ r := obj.Addrel(lsym)
+ r.Sym = tsym
+ r.Add = InterfaceMethodOffset(ityp, int64(ix))
+ r.Type = objabi.R_USEIFACEMETHOD
+}
+
// getDictionary returns the dictionary for the given named generic function
// or method, with the given type arguments.
func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node {