[dev.typeparams] cmd/compile: remove remaining uses of Unshapify

The other uses of Unshapify were really only there to allow for the
dictionary checking code at the beginning of generic functions/methods.
But that will go away as soon as we start combining real shapes. If we
get rid of that code, we can get rid of the unshapify calls elsewhere.

The only tricky part is that getInstantiation now gets targs that may each
either be a shape or concrete type, and it must translate any concrete
types to shapes, while leaving the already existing shapes.

Change-Id: Ib2b9072b921f8e064958548a1078d82f1d040c9f
Reviewed-on: https://go-review.googlesource.com/c/go/+/338289
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Dan Scales 2021-07-29 07:27:35 -07:00
parent 600b7b431b
commit 35dbdda2fe

View file

@ -768,38 +768,49 @@ func checkFetchBody(nameNode *ir.Name) {
} }
// getInstantiation gets the instantiantion and dictionary of the function or method nameNode // getInstantiation gets the instantiantion and dictionary of the function or method nameNode
// with the type arguments targs. If the instantiated function is not already // with the type arguments shapes. If the instantiated function is not already
// cached, then it calls genericSubst to create the new instantiation. // cached, then it calls genericSubst to create the new instantiation.
func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *ir.Func {
checkFetchBody(nameNode) checkFetchBody(nameNode)
// Convert type arguments to their shape, so we can reduce the number // Convert any non-shape type arguments to their shape, so we can reduce the
// of instantiations we have to generate. // number of instantiations we have to generate. You can actually have a mix
shapes := typecheck.ShapifyList(targs) // of shape and non-shape arguments, because of inferred or explicitly
// specified concrete type args.
var s1 []*types.Type
for i, t := range shapes {
if !t.HasShape() {
if s1 == nil {
s1 = make([]*types.Type, len(shapes))
for j := 0; j < i; j++ {
s1[j] = shapes[j]
}
}
s1[i] = typecheck.Shapify(t)
} else if s1 != nil {
s1[i] = shapes[i]
}
}
if s1 != nil {
shapes = s1
}
sym := typecheck.MakeInstName(nameNode.Sym(), shapes, isMeth) sym := typecheck.MakeInstName(nameNode.Sym(), shapes, isMeth)
info := g.instInfoMap[sym] info := g.instInfoMap[sym]
if info == nil { if info == nil {
if false {
// Testing out gcshapeType() and gcshapeName()
for i, t := range targs {
gct, gcs := gcshapeType(t)
fmt.Printf("targ %d: %v %v %v\n", i, gcs, gct, gct.Underlying())
}
}
// If instantiation doesn't exist yet, create it and add // If instantiation doesn't exist yet, create it and add
// to the list of decls. // to the list of decls.
gfInfo := g.getGfInfo(nameNode) gfInfo := g.getGfInfo(nameNode)
info = &instInfo{ info = &instInfo{
gf: nameNode, gf: nameNode,
gfInfo: gfInfo, gfInfo: gfInfo,
startSubDict: len(targs) + len(gfInfo.derivedTypes), startSubDict: len(shapes) + len(gfInfo.derivedTypes),
startItabConv: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls), startItabConv: len(shapes) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls),
dictLen: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls) + len(gfInfo.itabConvs), dictLen: len(shapes) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls) + len(gfInfo.itabConvs),
dictEntryMap: make(map[ir.Node]int), dictEntryMap: make(map[ir.Node]int),
} }
// genericSubst fills in info.dictParam and info.dictEntryMap. // genericSubst fills in info.dictParam and info.dictEntryMap.
st := g.genericSubst(sym, nameNode, shapes, targs, isMeth, info) st := g.genericSubst(sym, nameNode, shapes, isMeth, info)
info.fun = st info.fun = st
g.instInfoMap[sym] = info g.instInfoMap[sym] = info
// This ensures that the linker drops duplicates of this instantiation. // This ensures that the linker drops duplicates of this instantiation.
@ -821,23 +832,15 @@ type subster struct {
newf *ir.Func // Func node for the new stenciled function newf *ir.Func // Func node for the new stenciled function
ts typecheck.Tsubster ts typecheck.Tsubster
info *instInfo // Place to put extra info in the instantiation info *instInfo // Place to put extra info in the instantiation
// unshapeify maps from shape types to the concrete types they represent.
// TODO: remove when we no longer need it.
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,
// interface type> pair resides.
} }
// genericSubst returns a new function with name newsym. The function is an // genericSubst returns a new function with name newsym. The function is an
// instantiation of a generic function or method specified by namedNode with type // instantiation of a generic function or method specified by namedNode with type
// args targs. For a method with a generic receiver, it returns an instantiated // args shapes. For a method with a generic receiver, it returns an instantiated
// function type where the receiver becomes the first parameter. Otherwise the // function type where the receiver becomes the first parameter. For either a generic
// instantiated method would still need to be transformed by later compiler // method or function, a dictionary parameter is the added as the very first
// phases. genericSubst fills in info.dictParam and info.dictEntryMap. // parameter. genericSubst fills in info.dictParam and info.dictEntryMap.
func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs []*types.Type, isMethod bool, info *instInfo) *ir.Func { func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func {
var tparams []*types.Type var tparams []*types.Type
if isMethod { if isMethod {
// Get the type params from the method receiver (after skipping // Get the type params from the method receiver (after skipping
@ -852,11 +855,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
tparams[i] = f.Type tparams[i] = f.Type
} }
} }
for i := range targs {
if targs[i].HasShape() {
base.Fatalf("generiSubst shape %s %+v %+v\n", newsym.Name, shapes[i], targs[i])
}
}
gf := nameNode.Func gf := nameNode.Func
// Pos of the instantiated function is same as the generic function // Pos of the instantiated function is same as the generic function
newf := ir.NewFunc(gf.Pos()) newf := ir.NewFunc(gf.Pos())
@ -871,7 +869,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
ir.CurFunc = newf ir.CurFunc = newf
assert(len(tparams) == len(shapes)) assert(len(tparams) == len(shapes))
assert(len(tparams) == len(targs))
subst := &subster{ subst := &subster{
g: g, g: g,
@ -883,11 +880,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
Targs: shapes, Targs: shapes,
Vars: make(map[*ir.Name]*ir.Name), Vars: make(map[*ir.Name]*ir.Name),
}, },
unshapify: typecheck.Tsubster{
Tparams: shapes,
Targs: targs,
Vars: make(map[*ir.Name]*ir.Name),
},
} }
newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1)
@ -935,14 +927,14 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
newf.Body = subst.list(gf.Body) newf.Body = subst.list(gf.Body)
// Add code to check that the dictionary is correct. // Add code to check that the dictionary is correct.
// TODO: must go away when we move to many->1 shape to concrete mapping. // TODO: must be adjusted to deal with shapes, but will go away soon when we move
newf.Body.Prepend(subst.checkDictionary(dictionaryName, targs)...) // to many->1 shape to concrete mapping.
// newf.Body.Prepend(subst.checkDictionary(dictionaryName, shapes)...)
ir.CurFunc = savef ir.CurFunc = savef
// Add any new, fully instantiated types seen during the substitution to // Add any new, fully instantiated types seen during the substitution to
// g.instTypeList. // g.instTypeList.
g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...) g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...)
g.instTypeList = append(g.instTypeList, subst.unshapify.InstTypeList...)
if doubleCheck { if doubleCheck {
okConvs := map[ir.Node]bool{} okConvs := map[ir.Node]bool{}
@ -967,12 +959,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
return newf return newf
} }
func (subst *subster) unshapifyTyp(t *types.Type) *types.Type {
res := subst.unshapify.Typ(t)
types.CheckSize(res)
return res
}
// localvar creates a new name node for the specified local variable and enters it // localvar creates a new name node for the specified local variable and enters it
// in subst.vars. It substitutes type arguments for type parameters in the type of // in subst.vars. It substitutes type arguments for type parameters in the type of
// name as needed. // name as needed.
@ -1012,10 +998,7 @@ func (subst *subster) checkDictionary(name *ir.Name, targs []*types.Type) (code
for i, t := range targs { for i, t := range targs {
if t.HasShape() { if t.HasShape() {
// Check the concrete type, not the shape type. // Check the concrete type, not the shape type.
// TODO: can this happen?
//t = subst.unshapify.Typ(t)
base.Fatalf("shape type in dictionary %s %+v\n", name.Sym().Name, t) base.Fatalf("shape type in dictionary %s %+v\n", name.Sym().Name, t)
continue
} }
want := reflectdata.TypePtr(t) want := reflectdata.TypePtr(t)
typed(types.Types[types.TUINTPTR], want) typed(types.Types[types.TUINTPTR], want)
@ -1239,7 +1222,6 @@ func (subst *subster) node(n ir.Node) ir.Node {
// transform the call. // transform the call.
call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
transformDot(call.X.(*ir.SelectorExpr), true) transformDot(call.X.(*ir.SelectorExpr), true)
call.X.SetType(subst.unshapifyTyp(call.X.Type()))
transformCall(call) transformCall(call)
case ir.ODOT, ir.ODOTPTR: case ir.ODOT, ir.ODOTPTR:
@ -1367,15 +1349,6 @@ func (subst *subster) node(n ir.Node) ir.Node {
m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rt) m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rt)
m.SetType(dt.Type()) m.SetType(dt.Type())
m.SetTypecheck(1) m.SetTypecheck(1)
case ir.OFUNCINST:
inst := m.(*ir.InstExpr)
targs2 := make([]ir.Node, len(inst.Targs))
for i, n := range inst.Targs {
targs2[i] = ir.TypeNodeAt(n.Pos(), subst.unshapifyTyp(n.Type()))
// TODO: need an ir.Name node?
}
inst.Targs = targs2
} }
return m return m
} }