[dev.typeparams] cmd/compile: start using sub-dictionary entries where needed

Added new struct instInfo for information about an instantiation (of a
generic function/method with gcshapes or concrete types). We use this to
remember the dictionary param node, the nodes where sub-dictionaries
need to be used, etc. The instInfo map replaces the Stencil map in
Package.

Added code to access sub-dictionary entries at the appropriate call
sites. We are currently still calculating the corresponding main
dictionary, even when we really only need a sub-dictionary. I'll clean
that up in a follow-up CL.

Added code to deal with "generic" closures (closures that reference some
generic variables/types). We decided that closures will share the same
dictionary as the containing function (accessing the dictionary via a
closure variable). So, the getGfInfo function now traverses all the
nodes of each closure in a function that it is analyzing, so that a
function's dictionary has all the entries needed for all its closures as
well. Also, the instInfo of a closure is largely shared with its
containing function. A good test for generic closures already exists
with orderedmap.go.

Other improvements:
 - Only create sub-dictionary entries when the function/method
   call/value or closure actually has type params in it. Added new test
   file subdict.go with an example where a generic method has an
   instantiated method call that does not depend not have type params.

Change-Id: I691b9dc024a89d2305fcf1d8ba8540e53c9d103f
Reviewed-on: https://go-review.googlesource.com/c/go/+/331516
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-06-28 18:04:58 -07:00
parent a18726a648
commit 6dec18cc75
4 changed files with 309 additions and 112 deletions

View file

@ -100,11 +100,34 @@ func check2(noders []*noder) {
type gfInfo struct {
tparams []*types.Type
derivedTypes []*types.Type
// Node in generic function that requires a subdictionary. Some of these
// are not function/method values (not strictly calls).
// Nodes in generic function that requires a subdictionary. Includes
// method and function calls (OCALL), function values (OFUNCINST), method
// values/expressions (OXDOT).
subDictCalls []ir.Node
}
// instInfo is information gathered on an gcshape (or fully concrete)
// instantiation of a function.
type instInfo struct {
fun *ir.Func // The instantiated function (with body)
dictParam *ir.Name // The node inside fun that refers to the dictionary param
// Addr of static dictionary associated with this instantiation. This is the
// dictionary you should pass if all the type args are concreate. Soon to be
// removed, when creating static dictionary and instantiated function are
// separated.
dictAddr ir.Node
gf *ir.Name // The associated generic function
gfInfo *gfInfo
startSubDict int // Start of dict entries for subdictionaries
dictLen int // Total number of entries in dictionary
// Map from nodes in instantiated fun (OCALL, OCALLMETHOD, OFUNCINST, and
// OMETHEXPR) to the associated dictionary entry for a sub-dictionary
dictEntryMap map[ir.Node]int
}
type irgen struct {
target *ir.Package
self *types2.Package
@ -123,6 +146,11 @@ type irgen struct {
// Map from generic function to information about its type params, derived
// types, and subdictionaries.
gfInfoMap map[*types.Sym]*gfInfo
// Map from a name of function that been instantiated to information about
// its instantiated function, associated generic function/method, and the
// mapping from IR nodes to dictionary entries.
instInfoMap map[*types.Sym]*instInfo
}
func (g *irgen) generate(noders []*noder) {