// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file will evolve, since we plan to do a mix of stenciling and passing
// around dictionaries.

package noder

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/objw"
	"cmd/compile/internal/reflectdata"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
	"cmd/internal/obj"
	"cmd/internal/src"
	"fmt"
	"go/constant"
)

// Enable extra consistency checks.
const doubleCheck = false

func assert(p bool) {
	base.Assert(p)
}

// For outputting debug information on dictionary format and instantiated dictionaries
// (type arg, derived types, sub-dictionary, and itab entries).
var infoPrintMode = false

func infoPrint(format string, a ...interface{}) {
	if infoPrintMode {
		fmt.Printf(format, a...)
	}
}

var geninst genInst

func BuildInstantiations() {
	geninst.instInfoMap = make(map[*types.Sym]*instInfo)
	geninst.buildInstantiations()
	geninst.instInfoMap = nil
}

// buildInstantiations scans functions for generic function calls and methods, and
// creates the required instantiations. It also creates instantiated methods for all
// fully-instantiated generic types that have been encountered already or new ones
// that are encountered during the instantiation process. It scans all declarations
// in typecheck.Target.Decls first, before scanning any new instantiations created.
func (g *genInst) buildInstantiations() {
	// Instantiate the methods of instantiated generic types that we have seen so far.
	g.instantiateMethods()

	// Scan all currentdecls for call to generic functions/methods.
	n := len(typecheck.Target.Decls)
	for i := 0; i < n; i++ {
		g.scanForGenCalls(typecheck.Target.Decls[i])
	}

	// Scan all new instantiations created due to g.instantiateMethods() and the
	// scan of current decls. This loop purposely runs until no new
	// instantiations are created.
	for i := 0; i < len(g.newInsts); i++ {
		g.scanForGenCalls(g.newInsts[i])
	}

	g.finalizeSyms()

	// All the instantiations and dictionaries have been created. Now go through
	// each new instantiation and transform the various operations that need to make
	// use of their dictionary.
	l := len(g.newInsts)
	for _, fun := range g.newInsts {
		info := g.instInfoMap[fun.Sym()]
		g.dictPass(info)
		if doubleCheck {
			ir.Visit(info.fun, func(n ir.Node) {
				if n.Op() != ir.OCONVIFACE {
					return
				}
				c := n.(*ir.ConvExpr)
				if c.X.Type().HasShape() && !c.X.Type().IsInterface() {
					ir.Dump("BAD FUNCTION", info.fun)
					ir.Dump("BAD CONVERSION", c)
					base.Fatalf("converting shape type to interface")
				}
			})
		}
		if base.Flag.W > 1 {
			ir.Dump(fmt.Sprintf("\ndictpass %v", info.fun), info.fun)
		}
	}
	assert(l == len(g.newInsts))
	g.newInsts = nil
}

// scanForGenCalls scans a single function (or global assignment), looking for
// references to generic functions/methods. At each such reference, it creates any
// required instantiation and transforms the reference.
func (g *genInst) scanForGenCalls(decl ir.Node) {
	switch decl.Op() {
	case ir.ODCLFUNC:
		if decl.Type().HasTParam() {
			// Skip any generic functions
			return
		}
		// transformCall() below depends on CurFunc being set.
		ir.CurFunc = decl.(*ir.Func)

	case ir.OAS, ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV, ir.OASOP:
		// These are all the various kinds of global assignments,
		// whose right-hand-sides might contain a function
		// instantiation.

	default:
		// The other possible ops at the top level are ODCLCONST
		// and ODCLTYPE, which don't have any function
		// instantiations.
		return
	}

	// Search for any function references using generic function/methods. Then
	// create the needed instantiated function if it hasn't been created yet, and
	// change to calling that function directly.
	modified := false
	closureRequired := false
	// declInfo will be non-nil exactly if we are scanning an instantiated function
	declInfo := g.instInfoMap[decl.Sym()]

	ir.Visit(decl, func(n ir.Node) {
		if n.Op() == ir.OFUNCINST {
			// generic F, not immediately called
			closureRequired = true
		}
		if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) {
			// T.M or x.M, where T or x is generic, but not immediately
			// called. Not necessary if the method selected is
			// actually for an embedded interface field.
			closureRequired = true
		}
		if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST {
			// We have found a function call using a generic function
			// instantiation.
			call := n.(*ir.CallExpr)
			inst := call.X.(*ir.InstExpr)
			nameNode, isMeth := g.getInstNameNode(inst)
			targs := typecheck.TypesOf(inst.Targs)
			st := g.getInstantiation(nameNode, targs, isMeth).fun
			dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, nameNode, targs, isMeth)
			if infoPrintMode {
				dictkind := "Main dictionary"
				if usingSubdict {
					dictkind = "Sub-dictionary"
				}
				if inst.X.Op() == ir.OMETHVALUE {
					fmt.Printf("%s in %v at generic method call: %v - %v\n", dictkind, decl, inst.X, call)
				} else {
					fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call)
				}
			}

			// Transform the Call now, which changes OCALL to
			// OCALLFUNC and does typecheckaste/assignconvfn. Do
			// it before installing the instantiation, so we are
			// checking against non-shape param types in
			// typecheckaste.
			transformCall(call)

			// Replace the OFUNCINST with a direct reference to the
			// new stenciled function
			call.X = st.Nname
			if inst.X.Op() == ir.OMETHVALUE {
				// When we create an instantiation of a method
				// call, we make it a function. So, move the
				// receiver to be the first arg of the function
				// call.
				call.Args.Prepend(inst.X.(*ir.SelectorExpr).X)
			}

			// Add dictionary to argument list.
			call.Args.Prepend(dictValue)
			modified = true
		}
		if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 {
			// Method call on a generic type, which was instantiated by stenciling.
			// Method calls on explicitly instantiated types will have an OFUNCINST
			// and are handled above.
			call := n.(*ir.CallExpr)
			meth := call.X.(*ir.SelectorExpr)
			targs := deref(meth.Type().Recv().Type).RParams()

			t := meth.X.Type()
			baseType := deref(t).OrigType()
			var gf *ir.Name
			for _, m := range baseType.Methods().Slice() {
				if meth.Sel == m.Sym {
					gf = m.Nname.(*ir.Name)
					break
				}
			}

			// Transform the Call now, which changes OCALL
			// to OCALLFUNC and does typecheckaste/assignconvfn.
			transformCall(call)

			st := g.getInstantiation(gf, targs, true).fun
			dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true)
			if hasShapeTypes(targs) {
				// We have to be using a subdictionary, since this is
				// a generic method call.
				assert(usingSubdict)
			} else {
				// We should use main dictionary, because the receiver is
				// an instantiation already, see issue #53406.
				assert(!usingSubdict)
			}

			// Transform to a function call, by appending the
			// dictionary and the receiver to the args.
			call.SetOp(ir.OCALLFUNC)
			call.X = st.Nname
			call.Args.Prepend(dictValue, meth.X)
			modified = true
		}
	})

	// If we found a reference to a generic instantiation that wasn't an
	// immediate call, then traverse the nodes of decl again (with
	// EditChildren rather than Visit), where we actually change the
	// reference to the instantiation to a closure that captures the
	// dictionary, then does a direct call.
	// EditChildren is more expensive than Visit, so we only do this
	// in the infrequent case of an OFUNCINST without a corresponding
	// call.
	if closureRequired {
		modified = true
		var edit func(ir.Node) ir.Node
		var outer *ir.Func
		if f, ok := decl.(*ir.Func); ok {
			outer = f
		}
		edit = func(x ir.Node) ir.Node {
			if x.Op() == ir.OFUNCINST {
				child := x.(*ir.InstExpr).X
				if child.Op() == ir.OMETHEXPR || child.Op() == ir.OMETHVALUE {
					// Call EditChildren on child (x.X),
					// not x, so that we don't do
					// buildClosure() on the
					// METHEXPR/METHVALUE nodes as well.
					ir.EditChildren(child, edit)
					return g.buildClosure(outer, x)
				}
			}
			ir.EditChildren(x, edit)
			switch {
			case x.Op() == ir.OFUNCINST:
				return g.buildClosure(outer, x)
			case (x.Op() == ir.OMETHEXPR || x.Op() == ir.OMETHVALUE) &&
				len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 &&
				!types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type):
				return g.buildClosure(outer, x)
			}
			return x
		}
		edit(decl)
	}
	if base.Flag.W > 1 && modified {
		ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl)
	}
	ir.CurFunc = nil
	// We may have seen new fully-instantiated generic types while
	// instantiating any needed functions/methods in the above
	// function. If so, instantiate all the methods of those types
	// (which will then lead to more function/methods to scan in the loop).
	g.instantiateMethods()
}

// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR/OMETHVALUE
// of generic type. outer is the containing function (or nil if closure is
// in a global assignment instead of a function).
func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
	pos := x.Pos()
	var target *ir.Func   // target instantiated function/method
	var dictValue ir.Node // dictionary to use
	var rcvrValue ir.Node // receiver, if a method value
	typ := x.Type()       // type of the closure
	var outerInfo *instInfo
	if outer != nil {
		outerInfo = g.instInfoMap[outer.Sym()]
	}
	usingSubdict := false
	valueMethod := false
	if x.Op() == ir.OFUNCINST {
		inst := x.(*ir.InstExpr)

		// Type arguments we're instantiating with.
		targs := typecheck.TypesOf(inst.Targs)

		// Find the generic function/method.
		var gf *ir.Name
		if inst.X.Op() == ir.ONAME {
			// Instantiating a generic function call.
			gf = inst.X.(*ir.Name)
		} else if inst.X.Op() == ir.OMETHVALUE {
			// Instantiating a method value x.M.
			se := inst.X.(*ir.SelectorExpr)
			rcvrValue = se.X
			gf = se.Selection.Nname.(*ir.Name)
		} else {
			panic("unhandled")
		}

		// target is the instantiated function we're trying to call.
		// For functions, the target expects a dictionary as its first argument.
		// For method values, the target expects a dictionary and the receiver
		// as its first two arguments.
		// dictValue is the value to use for the dictionary argument.
		target = g.getInstantiation(gf, targs, rcvrValue != nil).fun
		dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, rcvrValue != nil)
		if infoPrintMode {
			dictkind := "Main dictionary"
			if usingSubdict {
				dictkind = "Sub-dictionary"
			}
			if rcvrValue == nil {
				fmt.Printf("%s in %v for generic function value %v\n", dictkind, outer, inst.X)
			} else {
				fmt.Printf("%s in %v for generic method value %v\n", dictkind, outer, inst.X)
			}
		}
	} else { // ir.OMETHEXPR or ir.METHVALUE
		// Method expression T.M where T is a generic type.
		se := x.(*ir.SelectorExpr)
		targs := deref(se.X.Type()).RParams()
		if len(targs) == 0 {
			panic("bad")
		}
		if x.Op() == ir.OMETHVALUE {
			rcvrValue = se.X
		}

		// se.X.Type() is the top-level type of the method expression. To
		// correctly handle method expressions involving embedded fields,
		// look up the generic method below using the type of the receiver
		// of se.Selection, since that will be the type that actually has
		// the method.
		recv := deref(se.Selection.Type.Recv().Type)
		if len(recv.RParams()) == 0 {
			// The embedded type that actually has the method is not
			// actually generic, so no need to build a closure.
			return x
		}
		baseType := recv.OrigType()
		var gf *ir.Name
		for _, m := range baseType.Methods().Slice() {
			if se.Sel == m.Sym {
				gf = m.Nname.(*ir.Name)
				break
			}
		}
		if !gf.Type().Recv().Type.IsPtr() {
			// Remember if value method, so we can detect (*T).M case.
			valueMethod = true
		}
		target = g.getInstantiation(gf, targs, true).fun
		dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true)
		if infoPrintMode {
			dictkind := "Main dictionary"
			if usingSubdict {
				dictkind = "Sub-dictionary"
			}
			fmt.Printf("%s in %v for method expression %v\n", dictkind, outer, x)
		}
	}

	// Build a closure to implement a function instantiation.
	//
	//   func f[T any] (int, int) (int, int) { ...whatever... }
	//
	// Then any reference to f[int] not directly called gets rewritten to
	//
	//   .dictN := ... dictionary to use ...
	//   func(a0, a1 int) (r0, r1 int) {
	//     return .inst.f[int](.dictN, a0, a1)
	//   }
	//
	// Similarly for method expressions,
	//
	//   type g[T any] ....
	//   func (rcvr g[T]) f(a0, a1 int) (r0, r1 int) { ... }
	//
	// Any reference to g[int].f not directly called gets rewritten to
	//
	//   .dictN := ... dictionary to use ...
	//   func(rcvr g[int], a0, a1 int) (r0, r1 int) {
	//     return .inst.g[int].f(.dictN, rcvr, a0, a1)
	//   }
	//
	// Also method values
	//
	//   var x g[int]
	//
	// Any reference to x.f not directly called gets rewritten to
	//
	//   .dictN := ... dictionary to use ...
	//   x2 := x
	//   func(a0, a1 int) (r0, r1 int) {
	//     return .inst.g[int].f(.dictN, x2, a0, a1)
	//   }

	// Make a new internal function.
	fn, formalParams, formalResults := startClosure(pos, outer, typ)
	fn.SetWrapper(true) // See issue 52237

	// This is the dictionary we want to use.
	// It may be a constant, it may be the outer functions's dictionary, or it may be
	// a subdictionary acquired from the outer function's dictionary.
	// For the latter, dictVar is a variable in the outer function's scope, set to the subdictionary
	// read from the outer function's dictionary.
	var dictVar *ir.Name
	var dictAssign *ir.AssignStmt
	if outer != nil {
		dictVar = ir.NewNameAt(pos, closureSym(outer, typecheck.LocalDictName, g.dnum))
		g.dnum++
		dictVar.Class = ir.PAUTO
		typed(types.Types[types.TUINTPTR], dictVar)
		dictVar.Curfn = outer
		dictAssign = ir.NewAssignStmt(pos, dictVar, dictValue)
		dictAssign.SetTypecheck(1)
		dictVar.Defn = dictAssign
		outer.Dcl = append(outer.Dcl, dictVar)
	}
	// assign the receiver to a temporary.
	var rcvrVar *ir.Name
	var rcvrAssign ir.Node
	if rcvrValue != nil {
		rcvrVar = ir.NewNameAt(pos, closureSym(outer, ".rcvr", g.dnum))
		g.dnum++
		typed(rcvrValue.Type(), rcvrVar)
		rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue)
		rcvrAssign.SetTypecheck(1)
		rcvrVar.Defn = rcvrAssign
		if outer == nil {
			rcvrVar.Class = ir.PEXTERN
			typecheck.Target.Decls = append(typecheck.Target.Decls, rcvrAssign)
			typecheck.Target.Externs = append(typecheck.Target.Externs, rcvrVar)
		} else {
			rcvrVar.Class = ir.PAUTO
			rcvrVar.Curfn = outer
			outer.Dcl = append(outer.Dcl, rcvrVar)
		}
	}

	// Build body of closure. This involves just calling the wrapped function directly
	// with the additional dictionary argument.

	// First, figure out the dictionary argument.
	var dict2Var ir.Node
	if usingSubdict {
		// Capture sub-dictionary calculated in the outer function
		dict2Var = ir.CaptureName(pos, fn, dictVar)
		typed(types.Types[types.TUINTPTR], dict2Var)
	} else {
		// Static dictionary, so can be used directly in the closure
		dict2Var = dictValue
	}
	// Also capture the receiver variable.
	var rcvr2Var *ir.Name
	if rcvrValue != nil {
		rcvr2Var = ir.CaptureName(pos, fn, rcvrVar)
	}

	// Build arguments to call inside the closure.
	var args []ir.Node

	// First the dictionary argument.
	args = append(args, dict2Var)
	// Then the receiver.
	if rcvrValue != nil {
		args = append(args, rcvr2Var)
	}
	// Then all the other arguments (including receiver for method expressions).
	for i := 0; i < typ.NumParams(); i++ {
		if x.Op() == ir.OMETHEXPR && i == 0 {
			// If we are doing a method expression, we need to
			// explicitly traverse any embedded fields in the receiver
			// argument in order to call the method instantiation.
			arg0 := formalParams[0].Nname.(ir.Node)
			arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(x.Pos(), ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X
			if valueMethod && arg0.Type().IsPtr() {
				// For handling the (*T).M case: if we have a pointer
				// receiver after following all the embedded fields,
				// but it's a value method, add a star operator.
				arg0 = ir.NewStarExpr(arg0.Pos(), arg0)
			}
			args = append(args, arg0)
		} else {
			args = append(args, formalParams[i].Nname.(*ir.Name))
		}
	}

	// Build call itself.
	var innerCall ir.Node = ir.NewCallExpr(pos, ir.OCALL, target.Nname, args)
	innerCall.(*ir.CallExpr).IsDDD = typ.IsVariadic()
	if len(formalResults) > 0 {
		innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall})
	}
	// Finish building body of closure.
	ir.CurFunc = fn
	// TODO: set types directly here instead of using typecheck.Stmt
	typecheck.Stmt(innerCall)
	ir.CurFunc = nil
	fn.Body = []ir.Node{innerCall}

	// We're all done with the captured dictionary (and receiver, for method values).
	ir.FinishCaptureNames(pos, outer, fn)

	// Make a closure referencing our new internal function.
	c := ir.UseClosure(fn.OClosure, typecheck.Target)
	var init []ir.Node
	if outer != nil {
		init = append(init, dictAssign)
	}
	if rcvrValue != nil {
		init = append(init, rcvrAssign)
	}
	return ir.InitExpr(init, c)
}

// instantiateMethods instantiates all the methods (and associated dictionaries) of
// all fully-instantiated generic types that have been added to typecheck.instTypeList.
// It continues until no more types are added to typecheck.instTypeList.
func (g *genInst) instantiateMethods() {
	for {
		instTypeList := typecheck.GetInstTypeList()
		if len(instTypeList) == 0 {
			break
		}
		typecheck.ClearInstTypeList()
		for _, typ := range instTypeList {
			assert(!typ.HasShape())
			// Mark runtime type as needed, since this ensures that the
			// compiler puts out the needed DWARF symbols, when this
			// instantiated type has a different package from the local
			// package.
			typecheck.NeedRuntimeType(typ)
			// Lookup the method on the base generic type, since methods may
			// not be set on imported instantiated types.
			baseType := typ.OrigType()
			for j, _ := range typ.Methods().Slice() {
				if baseType.Methods().Slice()[j].Nointerface() {
					typ.Methods().Slice()[j].SetNointerface(true)
				}
				baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
				// Eagerly generate the instantiations and dictionaries that implement these methods.
				// We don't use the instantiations here, just generate them (and any
				// further instantiations those generate, etc.).
				// Note that we don't set the Func for any methods on instantiated
				// types. Their signatures don't match so that would be confusing.
				// Direct method calls go directly to the instantiations, implemented above.
				// Indirect method calls use wrappers generated in reflectcall. Those wrappers
				// will use these instantiations if they are needed (for interface tables or reflection).
				_ = g.getInstantiation(baseNname, typ.RParams(), true)
				_ = g.getDictionarySym(baseNname, typ.RParams(), true)
			}
		}
	}
}

// getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated.
func (g *genInst) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) {
	if meth, ok := inst.X.(*ir.SelectorExpr); ok {
		return meth.Selection.Nname.(*ir.Name), true
	} else {
		return inst.X.(*ir.Name), false
	}
}

// getDictOrSubdict returns, for a method/function call or reference (node n) in an
// instantiation (described by instInfo), a node which is accessing a sub-dictionary
// or main/static dictionary, as needed, and also returns a boolean indicating if a
// sub-dictionary was accessed. nameNode is the particular function or method being
// called/referenced, and targs are the type arguments.
func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Name, targs []*types.Type, isMeth bool) (ir.Node, bool) {
	var dict ir.Node
	usingSubdict := false
	if declInfo != nil {
		entry := -1
		for i, de := range declInfo.dictInfo.subDictCalls {
			if n == de.callNode {
				entry = declInfo.dictInfo.startSubDict + i
				break
			}
		}
		// If the entry is not found, it may be that this node did not have
		// any type args that depend on type params, so we need a main
		// dictionary, not a sub-dictionary.
		if entry >= 0 {
			dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictInfo.dictLen)
			usingSubdict = true
		}
	}
	if !usingSubdict {
		dict = g.getDictionaryValue(n.Pos(), nameNode, targs, isMeth)
	}
	return dict, usingSubdict
}

// checkFetchBody checks if a generic body can be fetched, but hasn't been loaded
// yet. If so, it imports the body.
func checkFetchBody(nameNode *ir.Name) {
	if nameNode.Func.Body == nil && nameNode.Func.Inl != nil {
		// If there is no body yet but Func.Inl exists, then we can
		// import the whole generic body.
		assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg)
		typecheck.ImportBody(nameNode.Func)
		assert(nameNode.Func.Inl.Body != nil)
		nameNode.Func.Body = nameNode.Func.Inl.Body
		nameNode.Func.Dcl = nameNode.Func.Inl.Dcl
	}
}

// getInstantiation gets the instantiantion and dictionary of the function or method nameNode
// with the type arguments shapes. If the instantiated function is not already
// cached, then it calls genericSubst to create the new instantiation.
func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo {
	if nameNode.Func == nil {
		// If nameNode.Func is nil, this must be a reference to a method of
		// an imported instantiated type. We will have already called
		// g.instantiateMethods() on the fully-instantiated type, so
		// g.instInfoMap[sym] will be non-nil below.
		rcvr := nameNode.Type().Recv()
		if rcvr == nil || !deref(rcvr.Type).IsFullyInstantiated() {
			base.FatalfAt(nameNode.Pos(), "Unexpected function instantiation %v with no body", nameNode)
		}
	} else {
		checkFetchBody(nameNode)
	}

	var tparams []*types.Type
	if isMeth {
		// Get the type params from the method receiver (after skipping
		// over any pointer)
		recvType := nameNode.Type().Recv().Type
		recvType = deref(recvType)
		if recvType.IsFullyInstantiated() {
			// Get the type of the base generic type, so we get
			// its original typeparams.
			recvType = recvType.OrigType()
		}
		tparams = recvType.RParams()
	} else {
		fields := nameNode.Type().TParams().Fields().Slice()
		tparams = make([]*types.Type, len(fields))
		for i, f := range fields {
			tparams[i] = f.Type
		}
	}

	// Convert any non-shape type arguments to their shape, so we can reduce the
	// number of instantiations we have to generate. You can actually have a mix
	// of shape and non-shape arguments, because of inferred or explicitly
	// specified concrete type args.
	s1 := make([]*types.Type, len(shapes))
	for i, t := range shapes {
		var tparam *types.Type
		// Shapes are grouped differently for structural types, so we
		// pass the type param to Shapify(), so we can distinguish.
		tparam = tparams[i]
		if !t.IsShape() {
			s1[i] = typecheck.Shapify(t, i, tparam)
		} else {
			// Already a shape, but make sure it has the correct index.
			s1[i] = typecheck.Shapify(shapes[i].Underlying(), i, tparam)
		}
	}
	shapes = s1

	sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, false, isMeth)
	info := g.instInfoMap[sym]
	if info == nil {
		// If instantiation doesn't exist yet, create it and add
		// to the list of decls.
		info = &instInfo{
			dictInfo: &dictInfo{},
		}
		info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type)

		if sym.Def != nil {
			// This instantiation must have been imported from another
			// package (because it was needed for inlining), so we should
			// not re-generate it and have conflicting definitions for the
			// symbol (issue #50121). It will have already gone through the
			// dictionary transformations of dictPass, so we don't actually
			// need the info.dictParam and info.shapeToBound info filled in
			// below. We just set the imported instantiation as info.fun.
			assert(sym.Pkg != types.LocalPkg)
			info.fun = sym.Def.(*ir.Name).Func
			assert(info.fun != nil)
			g.instInfoMap[sym] = info
			return info
		}

		// genericSubst fills in info.dictParam and info.shapeToBound.
		st := g.genericSubst(sym, nameNode, tparams, shapes, isMeth, info)
		info.fun = st
		g.instInfoMap[sym] = info

		// getInstInfo fills in info.dictInfo.
		g.getInstInfo(st, shapes, info)
		if base.Flag.W > 1 {
			ir.Dump(fmt.Sprintf("\nstenciled %v", st), st)
		}

		// This ensures that the linker drops duplicates of this instantiation.
		// All just works!
		st.SetDupok(true)
		typecheck.Target.Decls = append(typecheck.Target.Decls, st)
		g.newInsts = append(g.newInsts, st)
	}
	return info
}

// Struct containing info needed for doing the substitution as we create the
// instantiation of a generic function with specified type arguments.
type subster struct {
	g           *genInst
	isMethod    bool     // If a method is being instantiated
	newf        *ir.Func // Func node for the new stenciled function
	ts          typecheck.Tsubster
	info        *instInfo // Place to put extra info in the instantiation
	skipClosure bool      // Skip substituting closures

	// Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n
	defnMap map[ir.Node][]**ir.Name
}

// genericSubst returns a new function with name newsym. The function is an
// instantiation of a generic function or method specified by namedNode with type
// args shapes. For a method with a generic receiver, it returns an instantiated
// function type where the receiver becomes the first parameter. For either a generic
// method or function, a dictionary parameter is the added as the very first
// parameter. genericSubst fills in info.dictParam and info.shapeToBound.
func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, tparams []*types.Type, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func {
	gf := nameNode.Func
	// Pos of the instantiated function is same as the generic function
	newf := ir.NewFunc(gf.Pos())
	newf.Pragma = gf.Pragma // copy over pragmas from generic function to stenciled implementation.
	newf.Endlineno = gf.Endlineno
	newf.Nname = ir.NewNameAt(gf.Pos(), newsym)
	newf.Nname.Func = newf
	newf.Nname.Defn = newf
	newsym.Def = newf.Nname
	savef := ir.CurFunc
	// transformCall/transformReturn (called during stenciling of the body)
	// depend on ir.CurFunc being set.
	ir.CurFunc = newf

	assert(len(tparams) == len(shapes))

	subst := &subster{
		g:        g,
		isMethod: isMethod,
		newf:     newf,
		info:     info,
		ts: typecheck.Tsubster{
			Tparams: tparams,
			Targs:   shapes,
			Vars:    make(map[*ir.Name]*ir.Name),
		},
		defnMap: make(map[ir.Node][]**ir.Name),
	}

	newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1)

	// Create the needed dictionary param
	dictionarySym := newsym.Pkg.Lookup(typecheck.LocalDictName)
	dictionaryType := types.Types[types.TUINTPTR]
	dictionaryName := ir.NewNameAt(gf.Pos(), dictionarySym)
	typed(dictionaryType, dictionaryName)
	dictionaryName.Class = ir.PPARAM
	dictionaryName.Curfn = newf
	newf.Dcl = append(newf.Dcl, dictionaryName)
	for _, n := range gf.Dcl {
		if n.Sym().Name == typecheck.LocalDictName {
			panic("already has dictionary")
		}
		newf.Dcl = append(newf.Dcl, subst.localvar(n))
	}
	dictionaryArg := types.NewField(gf.Pos(), dictionarySym, dictionaryType)
	dictionaryArg.Nname = dictionaryName
	info.dictParam = dictionaryName

	// We add the dictionary as the first parameter in the function signature.
	// We also transform a method type to the corresponding function type
	// (make the receiver be the next parameter after the dictionary).
	oldt := nameNode.Type()
	var args []*types.Field
	args = append(args, dictionaryArg)
	args = append(args, oldt.Recvs().FieldSlice()...)
	args = append(args, oldt.Params().FieldSlice()...)

	// Replace the types in the function signature via subst.fields.
	// Ugly: also, we have to insert the Name nodes of the parameters/results into
	// the function type. The current function type has no Nname fields set,
	// because it came via conversion from the types2 type.
	newt := types.NewSignature(oldt.Pkg(), nil, nil,
		subst.fields(ir.PPARAM, args, newf.Dcl),
		subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl))

	typed(newt, newf.Nname)
	ir.MarkFunc(newf.Nname)
	newf.SetTypecheck(1)

	// Make sure name/type of newf is set before substituting the body.
	newf.Body = subst.list(gf.Body)
	if len(newf.Body) == 0 {
		// Ensure the body is nonempty, for issue 49524.
		// TODO: have some other way to detect the difference between
		// a function declared with no body, vs. one with an empty body?
		newf.Body = append(newf.Body, ir.NewBlockStmt(gf.Pos(), nil))
	}

	if len(subst.defnMap) > 0 {
		base.Fatalf("defnMap is not empty")
	}

	for i, tp := range tparams {
		info.dictInfo.shapeToBound[shapes[i]] = subst.ts.Typ(tp.Bound())
	}

	ir.CurFunc = savef

	return subst.newf
}

// 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
// name as needed.
func (subst *subster) localvar(name *ir.Name) *ir.Name {
	m := ir.NewNameAt(name.Pos(), name.Sym())
	if name.IsClosureVar() {
		m.SetIsClosureVar(true)
	}
	m.SetType(subst.ts.Typ(name.Type()))
	m.BuiltinOp = name.BuiltinOp
	m.Curfn = subst.newf
	m.Class = name.Class
	assert(name.Class != ir.PEXTERN && name.Class != ir.PFUNC)
	m.Func = name.Func
	subst.ts.Vars[name] = m
	m.SetTypecheck(1)
	m.DictIndex = name.DictIndex
	if name.Defn != nil {
		if name.Defn.Op() == ir.ONAME {
			// This is a closure variable, so its Defn is the outer
			// captured variable, which has already been substituted.
			m.Defn = subst.node(name.Defn)
		} else {
			// The other values of Defn are nodes in the body of the
			// function, so just remember the mapping so we can set Defn
			// properly in node() when we create the new body node. We
			// always call localvar() on all the local variables before
			// we substitute the body.
			slice := subst.defnMap[name.Defn]
			subst.defnMap[name.Defn] = append(slice, &m)
		}
	}
	if name.Outer != nil {
		m.Outer = subst.node(name.Outer).(*ir.Name)
	}

	return m
}

// getDictionaryEntry gets the i'th entry in the dictionary dict.
func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node {
	// Convert dictionary to *[N]uintptr
	// All entries in the dictionary are pointers. They all point to static data, though, so we
	// treat them as uintptrs so the GC doesn't need to keep track of them.
	d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], dict)
	d.SetTypecheck(1)
	d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(size)).PtrTo(), d)
	d.SetTypecheck(1)
	types.CheckSize(d.Type().Elem())

	// Load entry i out of the dictionary.
	deref := ir.NewStarExpr(pos, d)
	typed(d.Type().Elem(), deref)
	idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), dict) // TODO: what to set orig to?
	typed(types.Types[types.TUINTPTR], idx)
	r := ir.NewIndexExpr(pos, deref, idx)
	typed(types.Types[types.TUINTPTR], r)
	return r
}

// getDictionaryEntryAddr gets the address of the i'th entry in dictionary dict.
func getDictionaryEntryAddr(pos src.XPos, dict *ir.Name, i int, size int) ir.Node {
	a := ir.NewAddrExpr(pos, getDictionaryEntry(pos, dict, i, size))
	typed(types.Types[types.TUINTPTR].PtrTo(), a)
	return a
}

// getDictionaryType returns a *runtime._type from the dictionary entry i (which
// refers to a type param or a derived type that uses type params). It uses the
// specified dictionary dictParam, rather than the one in info.dictParam.
func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int) ir.Node {
	if i < 0 || i >= info.dictInfo.startSubDict {
		base.Fatalf(fmt.Sprintf("bad dict index %d", i))
	}

	r := getDictionaryEntry(pos, dictParam, i, info.dictInfo.startSubDict)
	// change type of retrieved dictionary entry to *byte, which is the
	// standard typing of a *runtime._type in the compiler
	typed(types.Types[types.TUINT8].PtrTo(), r)
	return r
}

// node is like DeepCopy(), but substitutes ONAME nodes based on subst.ts.vars, and
// also descends into closures. It substitutes type arguments for type parameters in
// all the new nodes and does the transformations that were delayed on the generic
// function.
func (subst *subster) node(n ir.Node) ir.Node {
	// Use closure to capture all state needed by the ir.EditChildren argument.
	var edit func(ir.Node) ir.Node
	edit = func(x ir.Node) ir.Node {
		// Analogous to ir.SetPos() at beginning of typecheck.typecheck() -
		// allows using base.Pos during the transform functions, just like
		// the tc*() functions.
		ir.SetPos(x)
		switch x.Op() {
		case ir.OTYPE:
			return ir.TypeNode(subst.ts.Typ(x.Type()))

		case ir.ONAME:
			if v := subst.ts.Vars[x.(*ir.Name)]; v != nil {
				return v
			}
			if ir.IsBlank(x) {
				// Special case, because a blank local variable is
				// not in the fn.Dcl list.
				m := ir.NewNameAt(x.Pos(), ir.BlankNode.Sym())
				return typed(subst.ts.Typ(x.Type()), m)
			}
			return x
		case ir.ONONAME:
			// This handles the identifier in a type switch guard
			fallthrough
		case ir.OLITERAL, ir.ONIL:
			if x.Sym() != nil {
				return x
			}
		}
		m := ir.Copy(x)

		slice, ok := subst.defnMap[x]
		if ok {
			// We just copied a non-ONAME node which was the Defn value
			// of a local variable. Set the Defn value of the copied
			// local variable to this new Defn node.
			for _, ptr := range slice {
				(*ptr).Defn = m
			}
			delete(subst.defnMap, x)
		}

		if _, isExpr := m.(ir.Expr); isExpr {
			t := x.Type()
			if t == nil {
				// Check for known cases where t can be nil (call
				// that has no return values, and key expressions)
				// and otherwise cause a fatal error.
				_, isCallExpr := m.(*ir.CallExpr)
				_, isStructKeyExpr := m.(*ir.StructKeyExpr)
				_, isKeyExpr := m.(*ir.KeyExpr)
				if !isCallExpr && !isStructKeyExpr && !isKeyExpr && x.Op() != ir.OPANIC &&
					x.Op() != ir.OCLOSE {
					base.FatalfAt(m.Pos(), "Nil type for %v", x)
				}
			} else if x.Op() != ir.OCLOSURE {
				m.SetType(subst.ts.Typ(x.Type()))
			}
		}

		old := subst.skipClosure
		// For unsafe.{Alignof,Offsetof,Sizeof}, subster will transform them to OLITERAL nodes,
		// and discard their arguments. However, their children nodes were already process before,
		// thus if they contain any closure, the closure was still be added to package declarations
		// queue for processing later. Thus, genInst will fail to generate instantiation for the
		// closure because of lacking dictionary information, see issue #53390.
		if call, ok := m.(*ir.CallExpr); ok && call.X.Op() == ir.ONAME {
			switch call.X.Name().BuiltinOp {
			case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
				subst.skipClosure = true
			}
		}
		ir.EditChildren(m, edit)
		subst.skipClosure = old

		m.SetTypecheck(1)

		// Do the transformations that we delayed on the generic function
		// node, now that we have substituted in the type args.
		switch x.Op() {
		case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
			transformCompare(m.(*ir.BinaryExpr))

		case ir.OSLICE, ir.OSLICE3:
			transformSlice(m.(*ir.SliceExpr))

		case ir.OADD:
			m = transformAdd(m.(*ir.BinaryExpr))

		case ir.OINDEX:
			transformIndex(m.(*ir.IndexExpr))

		case ir.OAS2:
			as2 := m.(*ir.AssignListStmt)
			transformAssign(as2, as2.Lhs, as2.Rhs)

		case ir.OAS:
			as := m.(*ir.AssignStmt)
			if as.Y != nil {
				// transformAssign doesn't handle the case
				// of zeroing assignment of a dcl (rhs[0] is nil).
				lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y}
				transformAssign(as, lhs, rhs)
				as.X, as.Y = lhs[0], rhs[0]
			}

		case ir.OASOP:
			as := m.(*ir.AssignOpStmt)
			transformCheckAssign(as, as.X)

		case ir.ORETURN:
			transformReturn(m.(*ir.ReturnStmt))

		case ir.OSEND:
			transformSend(m.(*ir.SendStmt))

		case ir.OSELECT:
			transformSelect(m.(*ir.SelectStmt))

		case ir.OCOMPLIT:
			transformCompLit(m.(*ir.CompLitExpr))

		case ir.OADDR:
			transformAddr(m.(*ir.AddrExpr))

		case ir.OLITERAL:
			t := m.Type()
			if t != x.Type() {
				// types2 will give us a constant with a type T,
				// if an untyped constant is used with another
				// operand of type T (in a provably correct way).
				// When we substitute in the type args during
				// stenciling, we now know the real type of the
				// constant. We may then need to change the
				// BasicLit.val to be the correct type (e.g.
				// convert an int64Val constant to a floatVal
				// constant).
				m.SetType(types.UntypedInt) // use any untyped type for DefaultLit to work
				m = typecheck.DefaultLit(m, t)
			}

		case ir.OXDOT:
			// Finish the transformation of an OXDOT, unless this is
			// bound call or field access on a type param. A bound call
			// or field access on a type param will be transformed during
			// the dictPass. Otherwise, m will be transformed to an
			// OMETHVALUE node. It will be transformed to an ODOTMETH or
			// ODOTINTER node if we find in the OCALL case below that the
			// method value is actually called.
			mse := m.(*ir.SelectorExpr)
			if src := mse.X.Type(); !src.IsShape() {
				transformDot(mse, false)
			}

		case ir.OCALL:
			call := m.(*ir.CallExpr)
			switch call.X.Op() {
			case ir.OTYPE:
				// Transform the conversion, now that we know the
				// type argument.
				m = transformConvCall(call)

			case ir.OMETHVALUE, ir.OMETHEXPR:
				// Redo the transformation of OXDOT, now that we
				// know the method value is being called. Then
				// transform the call.
				call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
				transformDot(call.X.(*ir.SelectorExpr), true)
				transformCall(call)

			case ir.ODOT, ir.ODOTPTR:
				// An OXDOT for a generic receiver was resolved to
				// an access to a field which has a function
				// value. Transform the call to that function, now
				// that the OXDOT was resolved.
				transformCall(call)

			case ir.ONAME:
				name := call.X.Name()
				if name.BuiltinOp != ir.OXXX {
					m = transformBuiltin(call)
				} else {
					// This is the case of a function value that was a
					// type parameter (implied to be a function via a
					// structural constraint) which is now resolved.
					transformCall(call)
				}

			case ir.OFUNCINST:
				// A call with an OFUNCINST will get transformed
				// in stencil() once we have created & attached the
				// instantiation to be called.
				// We must transform the arguments of the call now, though,
				// so that any needed CONVIFACE nodes are exposed,
				// so the dictionary format is correct.
				transformEarlyCall(call)

			case ir.OXDOT:
				// This is the case of a bound call or a field access
				// on a typeparam, which will be handled in the
				// dictPass. As with OFUNCINST, we must transform the
				// arguments of the call now, so any needed CONVIFACE
				// nodes are exposed.
				transformEarlyCall(call)

			case ir.ODOTTYPE, ir.ODOTTYPE2:
				// These are DOTTYPEs that could get transformed into
				// ODYNAMIC DOTTYPEs by the dict pass.

			default:
				// Transform a call for all other values of
				// call.X.Op() that don't require any special
				// handling.
				transformCall(call)

			}

		case ir.OCLOSURE:
			if subst.skipClosure {
				break
			}
			// We're going to create a new closure from scratch, so clear m
			// to avoid using the ir.Copy by accident until we reassign it.
			m = nil

			x := x.(*ir.ClosureExpr)
			// Need to duplicate x.Func.Nname, x.Func.Dcl, x.Func.ClosureVars, and
			// x.Func.Body.
			oldfn := x.Func
			newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf != nil)
			ir.NameClosure(newfn.OClosure, subst.newf)

			saveNewf := subst.newf
			ir.CurFunc = newfn
			subst.newf = newfn
			newfn.Dcl = subst.namelist(oldfn.Dcl)

			// Make a closure variable for the dictionary of the
			// containing function.
			cdict := ir.CaptureName(oldfn.Pos(), newfn, subst.info.dictParam)
			typed(types.Types[types.TUINTPTR], cdict)
			ir.FinishCaptureNames(oldfn.Pos(), saveNewf, newfn)
			newfn.ClosureVars = append(newfn.ClosureVars, subst.namelist(oldfn.ClosureVars)...)

			// Copy that closure variable to a local one.
			// Note: this allows the dictionary to be captured by child closures.
			// See issue 47723.
			ldict := ir.NewNameAt(x.Pos(), newfn.Sym().Pkg.Lookup(typecheck.LocalDictName))
			typed(types.Types[types.TUINTPTR], ldict)
			ldict.Class = ir.PAUTO
			ldict.Curfn = newfn
			newfn.Dcl = append(newfn.Dcl, ldict)
			as := ir.NewAssignStmt(x.Pos(), ldict, cdict)
			as.SetTypecheck(1)
			ldict.Defn = as
			newfn.Body.Append(as)

			// Create inst info for the instantiated closure. The dict
			// param is the closure variable for the dictionary of the
			// outer function. Since the dictionary is shared, use the
			// same dictInfo.
			cinfo := &instInfo{
				fun:       newfn,
				dictParam: ldict,
				dictInfo:  subst.info.dictInfo,
			}
			subst.g.instInfoMap[newfn.Nname.Sym()] = cinfo

			typed(subst.ts.Typ(oldfn.Nname.Type()), newfn.Nname)
			typed(newfn.Nname.Type(), newfn.OClosure)
			newfn.SetTypecheck(1)

			outerinfo := subst.info
			subst.info = cinfo
			// Make sure type of closure function is set before doing body.
			newfn.Body.Append(subst.list(oldfn.Body)...)
			subst.info = outerinfo
			subst.newf = saveNewf
			ir.CurFunc = saveNewf

			m = ir.UseClosure(newfn.OClosure, typecheck.Target)
			subst.g.newInsts = append(subst.g.newInsts, m.(*ir.ClosureExpr).Func)
			m.(*ir.ClosureExpr).SetInit(subst.list(x.Init()))

		case ir.OSWITCH:
			m := m.(*ir.SwitchStmt)
			if m.Tag != nil && m.Tag.Op() == ir.OTYPESW {
				break // Nothing to do here for type switches.
			}
			if m.Tag != nil && !types.IsComparable(m.Tag.Type()) {
				break // Nothing to do here for un-comparable types.
			}
			if m.Tag != nil && !m.Tag.Type().IsEmptyInterface() && m.Tag.Type().HasShape() {
				// To implement a switch on a value that is or has a type parameter, we first convert
				// that thing we're switching on to an interface{}.
				m.Tag = assignconvfn(m.Tag, types.Types[types.TINTER])
			}
			for _, c := range m.Cases {
				for i, x := range c.List {
					// If we have a case that is or has a type parameter, convert that case
					// to an interface{}.
					if !x.Type().IsEmptyInterface() && x.Type().HasShape() {
						c.List[i] = assignconvfn(x, types.Types[types.TINTER])
					}
				}
			}

		}
		return m
	}

	return edit(n)
}

// dictPass takes a function instantiation and does the transformations on the
// operations that need to make use of the dictionary param.
func (g *genInst) dictPass(info *instInfo) {
	savef := ir.CurFunc
	ir.CurFunc = info.fun

	callMap := make(map[ir.Node]bool)

	var edit func(ir.Node) ir.Node
	edit = func(m ir.Node) ir.Node {
		if m.Op() == ir.OCALL && m.(*ir.CallExpr).X.Op() == ir.OXDOT {
			callMap[m.(*ir.CallExpr).X] = true
		}

		ir.EditChildren(m, edit)

		switch m.Op() {
		case ir.OCLOSURE:
			newf := m.(*ir.ClosureExpr).Func
			ir.CurFunc = newf
			outerinfo := info
			info = g.instInfoMap[newf.Nname.Sym()]

			body := newf.Body
			for i, n := range body {
				body[i] = edit(n)
			}

			info = outerinfo
			ir.CurFunc = info.fun

		case ir.OXDOT:
			// This is the case of a dot access on a type param. This is
			// typically a bound call on the type param, but could be a
			// field access, if the constraint has a single structural type.
			mse := m.(*ir.SelectorExpr)
			src := mse.X.Type()
			assert(src.IsShape())

			if mse.X.Op() == ir.OTYPE {
				// Method expression T.M
				idx := findMethodExprClosure(info.dictInfo, mse)
				c := getDictionaryEntryAddr(m.Pos(), info.dictParam, info.dictInfo.startMethodExprClosures+idx, info.dictInfo.dictLen)
				m = ir.NewConvExpr(m.Pos(), ir.OCONVNOP, mse.Type(), c)
				m.SetTypecheck(1)
			} else {
				// If we can't find the selected method in the
				// AllMethods of the bound, then this must be an access
				// to a field of a structural type. If so, we skip the
				// dictionary lookups - transformDot() will convert to
				// the desired direct field access.
				if isBoundMethod(info.dictInfo, mse) {
					if callMap[m] {
						// The OCALL surrounding this XDOT will rewrite the call
						// to use the method expression closure directly.
						break
					}
					// Convert this method value to a closure.
					// TODO: use method expression closure.
					dst := info.dictInfo.shapeToBound[mse.X.Type()]
					// Implement x.M as a conversion-to-bound-interface
					//  1) convert x to the bound interface
					//  2) select method value M on that interface
					if src.IsInterface() {
						// If type arg is an interface (unusual case),
						// we do a type assert to the type bound.
						mse.X = assertToBound(info, info.dictParam, m.Pos(), mse.X, dst)
					} else {
						mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst)
					}
				}
				transformDot(mse, false)
			}
		case ir.OCALL:
			call := m.(*ir.CallExpr)
			op := call.X.Op()
			if op == ir.OXDOT {
				// This is a call of a method value where the value has a type parameter type.
				// We transform to a call of the appropriate method expression closure
				// in the dictionary.
				// So if x has a type parameter type:
				//   _ = x.m(a)
				// Rewrite to:
				//   _ = methexpr<m>(x, a)
				se := call.X.(*ir.SelectorExpr)
				call.SetOp(ir.OCALLFUNC)
				idx := findMethodExprClosure(info.dictInfo, se)
				c := getDictionaryEntryAddr(se.Pos(), info.dictParam, info.dictInfo.startMethodExprClosures+idx, info.dictInfo.dictLen)
				t := typecheck.NewMethodType(se.Type(), se.X.Type())
				call.X = ir.NewConvExpr(se.Pos(), ir.OCONVNOP, t, c)
				typed(t, call.X)
				call.Args.Prepend(se.X)
				break
				// TODO: deref case?
			}
			if op == ir.OMETHVALUE {
				// Redo the transformation of OXDOT, now that we
				// know the method value is being called.
				call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
				transformDot(call.X.(*ir.SelectorExpr), true)
			}
			transformCall(call)

		case ir.OCONVIFACE:
			if m.Type().IsEmptyInterface() && m.(*ir.ConvExpr).X.Type().IsEmptyInterface() {
				// Was T->interface{}, after stenciling it is now interface{}->interface{}.
				// No longer need the conversion. See issue 48276.
				m.(*ir.ConvExpr).SetOp(ir.OCONVNOP)
				break
			}
			mce := m.(*ir.ConvExpr)
			// Note: x's argument is still typed as a type parameter.
			// m's argument now has an instantiated type.
			if mce.X.Type().HasShape() || (m.Type().HasShape() && !m.Type().IsEmptyInterface()) {
				m = convertUsingDictionary(info, info.dictParam, m.Pos(), mce.X, m, m.Type())
			}
		case ir.ODOTTYPE, ir.ODOTTYPE2:
			dt := m.(*ir.TypeAssertExpr)
			if !dt.Type().HasShape() && !dt.X.Type().HasShape() {
				break
			}
			var rtype, itab ir.Node
			if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() {
				// TODO(mdempsky): Investigate executing this block unconditionally.
				ix := findDictType(info, m.Type())
				assert(ix >= 0)
				rtype = getDictionaryType(info, info.dictParam, dt.Pos(), ix)
			} else {
				// nonempty interface to noninterface. Need an itab.
				ix := -1
				for i, ic := range info.dictInfo.itabConvs {
					if ic == m {
						ix = info.dictInfo.startItabConv + i
						break
					}
				}
				assert(ix >= 0)
				itab = getDictionaryEntry(dt.Pos(), info.dictParam, ix, info.dictInfo.dictLen)
			}
			op := ir.ODYNAMICDOTTYPE
			if m.Op() == ir.ODOTTYPE2 {
				op = ir.ODYNAMICDOTTYPE2
			}
			m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rtype)
			m.(*ir.DynamicTypeAssertExpr).ITab = itab
			m.SetType(dt.Type())
			m.SetTypecheck(1)
		case ir.OCASE:
			if _, ok := m.(*ir.CommClause); ok {
				// This is not a type switch. TODO: Should we use an OSWITCH case here instead of OCASE?
				break
			}
			m := m.(*ir.CaseClause)
			for i, c := range m.List {
				if c.Op() == ir.OTYPE && c.Type().HasShape() {
					// Use a *runtime._type for the dynamic type.
					ix := findDictType(info, m.List[i].Type())
					assert(ix >= 0)
					dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen))

					// For type switch from nonempty interfaces to non-interfaces, we need an itab as well.
					if !m.List[i].Type().IsInterface() {
						if _, ok := info.dictInfo.type2switchType[m.List[i]]; ok {
							// Type switch from nonempty interface. We need a *runtime.itab
							// for the dynamic type.
							ix := -1
							for j, ic := range info.dictInfo.itabConvs {
								if ic == m.List[i] {
									ix = info.dictInfo.startItabConv + j
									break
								}
							}
							assert(ix >= 0)
							dt.ITab = getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen)
						}
					}
					typed(m.List[i].Type(), dt)
					m.List[i] = dt
				}
			}

		}
		return m
	}
	edit(info.fun)
	ir.CurFunc = savef
}

// findDictType looks for type t in the typeparams or derived types in the generic
// function info.gfInfo. This will indicate the dictionary entry with the
// correct concrete type for the associated instantiated function.
func findDictType(info *instInfo, t *types.Type) int {
	for i, dt := range info.dictInfo.shapeParams {
		if dt == t {
			return i
		}
	}
	for i, dt := range info.dictInfo.derivedTypes {
		if types.IdenticalStrict(dt, t) {
			return i + len(info.dictInfo.shapeParams)
		}
	}
	return -1
}

// convertUsingDictionary converts instantiated value v (type v.Type()) to an interface
// type dst, by returning a new set of nodes that make use of a dictionary entry. in is the
// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the
// conversion.
func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node {
	assert(v.Type().HasShape() || (in.Type().HasShape() && !in.Type().IsEmptyInterface()))
	assert(dst.IsInterface())

	if v.Type().IsInterface() {
		// Converting from an interface. The shape-ness of the source doesn't really matter, as
		// we'll be using the concrete type from the first interface word.
		if dst.IsEmptyInterface() {
			// Converting I2E. OCONVIFACE does that for us, and doesn't depend
			// on what the empty interface was instantiated with. No dictionary entry needed.
			v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v)
			v.SetTypecheck(1)
			return v
		}
		if !in.Type().HasShape() {
			// Regular OCONVIFACE works if the destination isn't parameterized.
			v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v)
			v.SetTypecheck(1)
			return v
		}

		// We get the destination interface type from the dictionary and the concrete
		// type from the argument's itab. Call runtime.convI2I to get the new itab.
		tmp := typecheck.Temp(v.Type())
		as := ir.NewAssignStmt(pos, tmp, v)
		as.SetTypecheck(1)
		itab := ir.NewUnaryExpr(pos, ir.OITAB, tmp)
		typed(types.Types[types.TUINTPTR].PtrTo(), itab)
		idata := ir.NewUnaryExpr(pos, ir.OIDATA, tmp)
		typed(types.Types[types.TUNSAFEPTR], idata)

		fn := typecheck.LookupRuntime("convI2I")
		fn.SetTypecheck(1)
		types.CalcSize(fn.Type())
		call := ir.NewCallExpr(pos, ir.OCALLFUNC, fn, nil)
		typed(types.Types[types.TUINT8].PtrTo(), call)
		ix := findDictType(info, in.Type())
		assert(ix >= 0)
		inter := getDictionaryType(info, dictParam, pos, ix)
		call.Args = []ir.Node{inter, itab}
		i := ir.NewBinaryExpr(pos, ir.OEFACE, call, idata)
		typed(dst, i)
		i.PtrInit().Append(as)
		return i
	}

	var rt ir.Node
	if !dst.IsEmptyInterface() {
		// We should have an itab entry in the dictionary. Using this itab
		// will be more efficient than converting to an empty interface first
		// and then type asserting to dst.
		ix := -1
		for i, ic := range info.dictInfo.itabConvs {
			if ic == in {
				ix = info.dictInfo.startItabConv + i
				break
			}
		}
		assert(ix >= 0)
		rt = getDictionaryEntry(pos, dictParam, ix, info.dictInfo.dictLen)
	} else {
		ix := findDictType(info, v.Type())
		assert(ix >= 0)
		// Load the actual runtime._type of the type parameter from the dictionary.
		rt = getDictionaryType(info, dictParam, pos, ix)
	}

	// Figure out what the data field of the interface will be.
	data := ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v)
	typed(types.Types[types.TUNSAFEPTR], data)

	// Build an interface from the type and data parts.
	var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data)
	typed(dst, i)
	return i
}

func (subst *subster) namelist(l []*ir.Name) []*ir.Name {
	s := make([]*ir.Name, len(l))
	for i, n := range l {
		s[i] = subst.localvar(n)
	}
	return s
}

func (subst *subster) list(l []ir.Node) []ir.Node {
	s := make([]ir.Node, len(l))
	for i, n := range l {
		s[i] = subst.node(n)
	}
	return s
}

// fields sets the Nname field for the Field nodes inside a type signature, based
// on the corresponding in/out parameters in dcl. It depends on the in and out
// parameters being in order in dcl.
func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir.Name) []*types.Field {
	// Find the starting index in dcl of declarations of the class (either
	// PPARAM or PPARAMOUT).
	var i int
	for i = range dcl {
		if dcl[i].Class == class {
			break
		}
	}

	// Create newfields nodes that are copies of the oldfields nodes, but
	// with substitution for any type params, and with Nname set to be the node in
	// Dcl for the corresponding PPARAM or PPARAMOUT.
	newfields := make([]*types.Field, len(oldfields))
	for j := range oldfields {
		newfields[j] = oldfields[j].Copy()
		newfields[j].Type = subst.ts.Typ(oldfields[j].Type)
		// A PPARAM field will be missing from dcl if its name is
		// unspecified or specified as "_". So, we compare the dcl sym
		// with the field sym (or sym of the field's Nname node). (Unnamed
		// results still have a name like ~r2 in their Nname node.) If
		// they don't match, this dcl (if there is one left) must apply to
		// a later field.
		if i < len(dcl) && (dcl[i].Sym() == oldfields[j].Sym ||
			(oldfields[j].Nname != nil && dcl[i].Sym() == oldfields[j].Nname.Sym())) {
			newfields[j].Nname = dcl[i]
			i++
		}
	}
	return newfields
}

// deref does a single deref of type t, if it is a pointer type.
func deref(t *types.Type) *types.Type {
	if t.IsPtr() {
		return t.Elem()
	}
	return t
}

// markTypeUsed marks type t as used in order to help avoid dead-code elimination of
// needed methods.
func markTypeUsed(t *types.Type, lsym *obj.LSym) {
	if t.IsInterface() {
		return
	}
	// TODO: This is somewhat overkill, we really only need it
	// for types that are put into interfaces.
	// Note: this relocation is also used in cmd/link/internal/ld/dwarf.go
	reflectdata.MarkTypeUsedInInterface(t, lsym)
}

// getDictionarySym returns the dictionary for the named generic function gf, which
// is instantiated with the type arguments targs.
func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) *types.Sym {
	if len(targs) == 0 {
		base.Fatalf("%s should have type arguments", gf.Sym().Name)
	}

	// Enforce that only concrete types can make it to here.
	for _, t := range targs {
		if t.HasShape() {
			panic(fmt.Sprintf("shape %+v in dictionary for %s", t, gf.Sym().Name))
		}
	}

	// Get a symbol representing the dictionary.
	sym := typecheck.MakeDictSym(gf.Sym(), targs, isMeth)

	// Initialize the dictionary, if we haven't yet already.
	lsym := sym.Linksym()
	if len(lsym.P) > 0 {
		// We already started creating this dictionary and its lsym.
		return sym
	}

	infoPrint("=== Creating dictionary %v\n", sym.Name)
	off := 0
	// Emit an entry for each targ (concrete type or gcshape).
	for _, t := range targs {
		infoPrint(" * %v\n", t)
		s := reflectdata.TypeLinksym(t)
		off = objw.SymPtr(lsym, off, s, 0)
		markTypeUsed(t, lsym)
	}

	instInfo := g.getInstantiation(gf, targs, isMeth)
	info := instInfo.dictInfo

	subst := typecheck.Tsubster{
		Tparams: info.shapeParams,
		Targs:   targs,
	}
	// Emit an entry for each derived type (after substituting targs)
	for _, t := range info.derivedTypes {
		ts := subst.Typ(t)
		infoPrint(" - %v\n", ts)
		s := reflectdata.TypeLinksym(ts)
		off = objw.SymPtr(lsym, off, s, 0)
		markTypeUsed(ts, lsym)
	}
	// Emit an entry for each subdictionary (after substituting targs)
	for _, subDictInfo := range info.subDictCalls {
		var sym *types.Sym
		n := subDictInfo.callNode
		switch n.Op() {
		case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH:
			call := n.(*ir.CallExpr)
			if call.X.Op() == ir.OXDOT || call.X.Op() == ir.ODOTMETH {
				var nameNode *ir.Name
				se := call.X.(*ir.SelectorExpr)
				if se.X.Type().IsShape() {
					// This is a method call enabled by a type bound.
					tparam := se.X.Type()
					if call.X.Op() == ir.ODOTMETH {
						// We need this extra check for method expressions,
						// which don't add in the implicit XDOTs.
						tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel)
						tmpse = typecheck.AddImplicitDots(tmpse)
						tparam = tmpse.X.Type()
					}
					if !tparam.IsShape() {
						// The method expression is not
						// really on a typeparam.
						break
					}
					ix := -1
					for i, shape := range info.shapeParams {
						if shape == tparam {
							ix = i
							break
						}
					}
					assert(ix >= 0)
					recvType := targs[ix]
					if recvType.IsInterface() || len(recvType.RParams()) == 0 {
						// No sub-dictionary entry is
						// actually needed, since the
						// type arg is not an
						// instantiated type that
						// will have generic methods.
						break
					}
					// This is a method call for an
					// instantiated type, so we need a
					// sub-dictionary.
					targs := recvType.RParams()
					genRecvType := recvType.OrigType()
					nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
					sym = g.getDictionarySym(nameNode, targs, true)
				} else {
					// This is the case of a normal
					// method call on a generic type.
					assert(subDictInfo.savedXNode == se)
					sym = g.getSymForMethodCall(se, &subst)
				}
			} else {
				inst, ok := call.X.(*ir.InstExpr)
				if ok {
					// Code hasn't been transformed yet
					assert(subDictInfo.savedXNode == inst)
				}
				// If !ok, then the generic method/function call has
				// already been transformed to a shape instantiation
				// call. Either way, use the SelectorExpr/InstExpr
				// node saved in info.
				cex := subDictInfo.savedXNode
				if se, ok := cex.(*ir.SelectorExpr); ok {
					sym = g.getSymForMethodCall(se, &subst)
				} else {
					inst := cex.(*ir.InstExpr)
					nameNode := inst.X.(*ir.Name)
					subtargs := typecheck.TypesOf(inst.Targs)
					for i, t := range subtargs {
						subtargs[i] = subst.Typ(t)
					}
					sym = g.getDictionarySym(nameNode, subtargs, false)
				}
			}

		case ir.OFUNCINST:
			inst := n.(*ir.InstExpr)
			nameNode := inst.X.(*ir.Name)
			subtargs := typecheck.TypesOf(inst.Targs)
			for i, t := range subtargs {
				subtargs[i] = subst.Typ(t)
			}
			sym = g.getDictionarySym(nameNode, subtargs, false)

		case ir.OXDOT, ir.OMETHEXPR, ir.OMETHVALUE:
			sym = g.getSymForMethodCall(n.(*ir.SelectorExpr), &subst)

		default:
			assert(false)
		}

		if sym == nil {
			// Unused sub-dictionary entry, just emit 0.
			off = objw.Uintptr(lsym, off, 0)
			infoPrint(" - Unused subdict entry\n")
		} else {
			off = objw.SymPtr(lsym, off, sym.Linksym(), 0)
			infoPrint(" - Subdict %v\n", sym.Name)
		}
	}

	g.instantiateMethods()
	delay := &delayInfo{
		gf:     gf,
		targs:  targs,
		sym:    sym,
		off:    off,
		isMeth: isMeth,
	}
	g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay)
	return sym
}

// getSymForMethodCall gets the dictionary sym for a method call, method value, or method
// expression that has selector se. subst gives the substitution from shape types to
// concrete types.
func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsubster) *types.Sym {
	// For everything except method expressions, 'recvType = deref(se.X.Type)' would
	// also give the receiver type. For method expressions with embedded types, we
	// need to look at the type of the selection to get the final receiver type.
	recvType := deref(se.Selection.Type.Recv().Type)
	genRecvType := recvType.OrigType()
	nameNode := typecheck.Lookdot1(se, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
	subtargs := recvType.RParams()
	s2targs := make([]*types.Type, len(subtargs))
	for i, t := range subtargs {
		s2targs[i] = subst.Typ(t)
	}
	return g.getDictionarySym(nameNode, s2targs, true)
}

// finalizeSyms finishes up all dictionaries on g.dictSymsToFinalize, by writing out
// any needed LSyms for itabs. The itab lsyms create wrappers which need various
// dictionaries and method instantiations to be complete, so, to avoid recursive
// dependencies, we finalize the itab lsyms only after all dictionaries syms and
// instantiations have been created.
// Also handles writing method expression closures into the dictionaries.
func (g *genInst) finalizeSyms() {
	for _, d := range g.dictSymsToFinalize {
		infoPrint("=== Finalizing dictionary %s\n", d.sym.Name)

		lsym := d.sym.Linksym()
		instInfo := g.getInstantiation(d.gf, d.targs, d.isMeth)
		info := instInfo.dictInfo

		subst := typecheck.Tsubster{
			Tparams: info.shapeParams,
			Targs:   d.targs,
		}

		// Emit an entry for each itab
		for _, n := range info.itabConvs {
			var srctype, dsttype *types.Type
			switch n.Op() {
			case ir.OXDOT, ir.OMETHVALUE:
				se := n.(*ir.SelectorExpr)
				srctype = subst.Typ(se.X.Type())
				dsttype = subst.Typ(info.shapeToBound[se.X.Type()])
			case ir.ODOTTYPE, ir.ODOTTYPE2:
				srctype = subst.Typ(n.(*ir.TypeAssertExpr).Type())
				dsttype = subst.Typ(n.(*ir.TypeAssertExpr).X.Type())
			case ir.OCONVIFACE:
				srctype = subst.Typ(n.(*ir.ConvExpr).X.Type())
				dsttype = subst.Typ(n.Type())
			case ir.OTYPE:
				srctype = subst.Typ(n.Type())
				dsttype = subst.Typ(info.type2switchType[n])
			default:
				base.Fatalf("itab entry with unknown op %s", n.Op())
			}
			if srctype.IsInterface() || dsttype.IsEmptyInterface() {
				// No itab is wanted if src type is an interface. We
				// will use a type assert instead.
				d.off = objw.Uintptr(lsym, d.off, 0)
				infoPrint(" + Unused itab entry for %v\n", srctype)
			} else {
				// Make sure all new fully-instantiated types have
				// their methods created before generating any itabs.
				g.instantiateMethods()
				itabLsym := reflectdata.ITabLsym(srctype, dsttype)
				d.off = objw.SymPtr(lsym, d.off, itabLsym, 0)
				markTypeUsed(srctype, lsym)
				infoPrint(" + Itab for (%v,%v)\n", srctype, dsttype)
			}
		}

		// Emit an entry for each method expression closure.
		// Each entry is a (captureless) closure pointing to the method on the instantiating type.
		// In other words, the entry is a runtime.funcval whose fn field is set to the method
		// in question, and has no other fields. The address of this dictionary entry can be
		// cast to a func of the appropriate type.
		// TODO: do these need to be done when finalizing, or can we do them earlier?
		for _, bf := range info.methodExprClosures {
			rcvr := d.targs[bf.idx]
			rcvr2 := deref(rcvr)
			found := false
			typecheck.CalcMethods(rcvr2) // Ensure methods on all instantiating types are computed.
			for _, f := range rcvr2.AllMethods().Slice() {
				if f.Sym.Name == bf.name {
					codePtr := ir.MethodSym(rcvr, f.Sym).Linksym()
					d.off = objw.SymPtr(lsym, d.off, codePtr, 0)
					infoPrint(" + MethodExprClosure for %v.%s\n", rcvr, bf.name)
					found = true
					break
				}
			}
			if !found {
				base.Fatalf("method %s on %v not found", bf.name, rcvr)
			}
		}

		objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA)
		infoPrint("=== Finalized dictionary %s\n", d.sym.Name)
	}
	g.dictSymsToFinalize = nil
}

func (g *genInst) getDictionaryValue(pos src.XPos, gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node {
	sym := g.getDictionarySym(gf, targs, isMeth)

	// Make (or reuse) a node referencing the dictionary symbol.
	var n *ir.Name
	if sym.Def != nil {
		n = sym.Def.(*ir.Name)
	} else {
		// We set the position of a static dictionary to be the position of
		// one of its uses.
		n = ir.NewNameAt(pos, sym)
		n.Curfn = ir.CurFunc
		n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter
		n.SetTypecheck(1)
		n.Class = ir.PEXTERN
		sym.Def = n
	}

	// Return the address of the dictionary.  Addr node gets position that was passed in.
	np := typecheck.NodAddrAt(pos, n)
	// Note: treat dictionary pointers as uintptrs, so they aren't pointers
	// with respect to GC. That saves on stack scanning work, write barriers, etc.
	// We can get away with it because dictionaries are global variables.
	// TODO: use a cast, or is typing directly ok?
	np.SetType(types.Types[types.TUINTPTR])
	np.SetTypecheck(1)
	return np
}

// hasShapeNodes returns true if the type of any node in targs has a shape.
func hasShapeNodes(targs []ir.Ntype) bool {
	for _, n := range targs {
		if n.Type().HasShape() {
			return true
		}
	}
	return false
}

// hasShapeTypes returns true if any type in targs has a shape.
func hasShapeTypes(targs []*types.Type) bool {
	for _, t := range targs {
		if t.HasShape() {
			return true
		}
	}
	return false
}

// getInstInfo get the dictionary format for a function instantiation- type params, derived
// types, and needed subdictionaries, itabs, and method expression closures.
func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) {
	info := instInfo.dictInfo
	info.shapeParams = shapes

	for _, t := range info.shapeParams {
		b := info.shapeToBound[t]
		if b.HasShape() {
			// If a type bound is parameterized (unusual case), then we
			// may need its derived type to do a type assert when doing a
			// bound call for a type arg that is an interface.
			addType(info, nil, b)
		}
	}

	for _, n := range st.Dcl {
		addType(info, n, n.Type())
		n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1)
	}

	if infoPrintMode {
		fmt.Printf(">>> InstInfo for %v\n", st)
		for _, t := range info.shapeParams {
			fmt.Printf("  Typeparam %v\n", t)
		}
	}

	// Map to remember when we have seen an instantiated function value or method
	// expression/value as part of a call, so we can determine when we encounter
	// an uncalled function value or method expression/value.
	callMap := make(map[ir.Node]bool)

	var visitFunc func(ir.Node)
	visitFunc = func(n ir.Node) {
		switch n.Op() {
		case ir.OFUNCINST:
			if !callMap[n] && hasShapeNodes(n.(*ir.InstExpr).Targs) {
				infoPrint("  Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X)
				info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
			}
		case ir.OMETHEXPR, ir.OMETHVALUE:
			if !callMap[n] && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) &&
				len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 &&
				hasShapeTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) {
				if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE {
					infoPrint("  Closure&subdictionary required at generic meth expr %v\n", n)
				} else {
					infoPrint("  Closure&subdictionary required at generic meth value %v\n", n)
				}
				info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
			}
		case ir.OCALL:
			ce := n.(*ir.CallExpr)
			if ce.X.Op() == ir.OFUNCINST {
				callMap[ce.X] = true
				if hasShapeNodes(ce.X.(*ir.InstExpr).Targs) {
					infoPrint("  Subdictionary at generic function/method call: %v - %v\n", ce.X.(*ir.InstExpr).X, n)
					// Save the instExpr node for the function call,
					// since we will lose this information when the
					// generic function call is transformed to a call
					// on the shape instantiation.
					info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: ce.X})
				}
			}
			// Note: this XDOT code is not actually needed as long as we
			// continue to disable type parameters on RHS of type
			// declarations (#45639).
			if ce.X.Op() == ir.OXDOT {
				callMap[ce.X] = true
				if isBoundMethod(info, ce.X.(*ir.SelectorExpr)) {
					infoPrint("  Optional subdictionary at generic bound call: %v\n", n)
					info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
				}
			}
		case ir.OCALLMETH:
			ce := n.(*ir.CallExpr)
			if ce.X.Op() == ir.ODOTMETH &&
				len(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 {
				callMap[ce.X] = true
				if hasShapeTypes(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) {
					infoPrint("  Subdictionary at generic method call: %v\n", n)
					// Save the selector for the method call, since we
					// will eventually lose this information when the
					// generic method call is transformed into a
					// function call on the method shape instantiation.
					info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: ce.X})
				}
			}
		case ir.OCONVIFACE:
			if n.Type().IsInterface() && !n.Type().IsEmptyInterface() &&
				(n.Type().HasShape() || n.(*ir.ConvExpr).X.Type().HasShape()) {
				infoPrint("  Itab for interface conv: %v\n", n)
				info.itabConvs = append(info.itabConvs, n)
			}
		case ir.OXDOT:
			se := n.(*ir.SelectorExpr)
			if se.X.Op() == ir.OTYPE && se.X.Type().IsShape() {
				// Method expression.
				addMethodExprClosure(info, se)
				break
			}
			if isBoundMethod(info, se) {
				if callMap[n] {
					// Method value called directly. Use method expression closure.
					addMethodExprClosure(info, se)
					break
				}
				// Method value not called directly. Still doing the old way.
				infoPrint("  Itab for bound call: %v\n", n)
				info.itabConvs = append(info.itabConvs, n)
			}

		case ir.ODOTTYPE, ir.ODOTTYPE2:
			if !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() {
				infoPrint("  Itab for dot type: %v\n", n)
				info.itabConvs = append(info.itabConvs, n)
			}
		case ir.OCLOSURE:
			// Visit the closure body and add all relevant entries to the
			// dictionary of the outer function (closure will just use
			// the dictionary of the outer function).
			cfunc := n.(*ir.ClosureExpr).Func
			for _, n1 := range cfunc.Body {
				ir.Visit(n1, visitFunc)
			}
			for _, n := range cfunc.Dcl {
				n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1)
			}
		case ir.OSWITCH:
			ss := n.(*ir.SwitchStmt)
			if ss.Tag != nil && ss.Tag.Op() == ir.OTYPESW &&
				!ss.Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() {
				for _, cc := range ss.Cases {
					for _, c := range cc.List {
						if c.Op() == ir.OTYPE && c.Type().HasShape() {
							// Type switch from a non-empty interface - might need an itab.
							infoPrint("  Itab for type switch: %v\n", c)
							info.itabConvs = append(info.itabConvs, c)
							if info.type2switchType == nil {
								info.type2switchType = map[ir.Node]*types.Type{}
							}
							info.type2switchType[c] = ss.Tag.(*ir.TypeSwitchGuard).X.Type()
						}
					}
				}
			}
		}
		addType(info, n, n.Type())
	}

	for _, stmt := range st.Body {
		ir.Visit(stmt, visitFunc)
	}
	if infoPrintMode {
		for _, t := range info.derivedTypes {
			fmt.Printf("  Derived type %v\n", t)
		}
		fmt.Printf(">>> Done Instinfo\n")
	}
	info.startSubDict = len(info.shapeParams) + len(info.derivedTypes)
	info.startItabConv = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls)
	info.startMethodExprClosures = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs)
	info.dictLen = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs) + len(info.methodExprClosures)
}

// isBoundMethod returns true if the selection indicated by se is a bound method of
// se.X. se.X must be a shape type (i.e. substituted directly from a type param). If
// isBoundMethod returns false, then the selection must be a field access of a
// structural type.
func isBoundMethod(info *dictInfo, se *ir.SelectorExpr) bool {
	bound := info.shapeToBound[se.X.Type()]
	return typecheck.Lookdot1(se, se.Sel, bound, bound.AllMethods(), 1) != nil
}

func shapeIndex(info *dictInfo, t *types.Type) int {
	for i, s := range info.shapeParams {
		if s == t {
			return i
		}
	}
	base.Fatalf("can't find type %v in shape params", t)
	return -1
}

// addMethodExprClosure adds the T.M method expression to the list of bound method expressions
// used in the generic body.
// isBoundMethod must have returned true on the same arguments.
func addMethodExprClosure(info *dictInfo, se *ir.SelectorExpr) {
	idx := shapeIndex(info, se.X.Type())
	name := se.Sel.Name
	for _, b := range info.methodExprClosures {
		if idx == b.idx && name == b.name {
			return
		}
	}
	infoPrint("  Method expression closure for %v.%s\n", info.shapeParams[idx], name)
	info.methodExprClosures = append(info.methodExprClosures, methodExprClosure{idx: idx, name: name})
}

// findMethodExprClosure finds the entry in the dictionary to use for the T.M
// method expression encoded in se.
// isBoundMethod must have returned true on the same arguments.
func findMethodExprClosure(info *dictInfo, se *ir.SelectorExpr) int {
	idx := shapeIndex(info, se.X.Type())
	name := se.Sel.Name
	for i, b := range info.methodExprClosures {
		if idx == b.idx && name == b.name {
			return i
		}
	}
	base.Fatalf("can't find method expression closure for %s %s", se.X.Type(), name)
	return -1
}

// addType adds t to info.derivedTypes if it is parameterized type (which is not
// just a simple shape) that is different from any existing type on
// info.derivedTypes.
func addType(info *dictInfo, n ir.Node, t *types.Type) {
	if t == nil || !t.HasShape() {
		return
	}
	if t.IsShape() {
		return
	}
	if t.Kind() == types.TFUNC && n != nil &&
		(t.Recv() != nil || n.Op() == ir.ONAME && n.Name().Class == ir.PFUNC) {
		// Don't use the type of a named generic function or method,
		// since that is parameterized by other typeparams.
		// (They all come from arguments of a FUNCINST node.)
		return
	}
	if doubleCheck && !parameterizedBy(t, info.shapeParams) {
		base.Fatalf("adding type with invalid parameters %+v", t)
	}
	if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() {
		// Multiple return values are not a relevant new type (?).
		return
	}
	// Ignore a derived type we've already added.
	for _, et := range info.derivedTypes {
		if types.IdenticalStrict(t, et) {
			return
		}
	}
	info.derivedTypes = append(info.derivedTypes, t)
}

// parameterizedBy returns true if t is parameterized by (at most) params.
func parameterizedBy(t *types.Type, params []*types.Type) bool {
	return parameterizedBy1(t, params, map[*types.Type]bool{})
}
func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Type]bool) bool {
	if visited[t] {
		return true
	}
	visited[t] = true

	if t.Sym() != nil && len(t.RParams()) > 0 {
		// This defined type is instantiated. Check the instantiating types.
		for _, r := range t.RParams() {
			if !parameterizedBy1(r, params, visited) {
				return false
			}
		}
		return true
	}
	if t.IsShape() {
		// Check if t is one of the allowed parameters in scope.
		for _, p := range params {
			if p == t {
				return true
			}
		}
		// Couldn't find t in the list of allowed parameters.
		return false

	}
	switch t.Kind() {
	case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN:
		return parameterizedBy1(t.Elem(), params, visited)

	case types.TMAP:
		return parameterizedBy1(t.Key(), params, visited) && parameterizedBy1(t.Elem(), params, visited)

	case types.TFUNC:
		return parameterizedBy1(t.TParams(), params, visited) && parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited)

	case types.TSTRUCT:
		for _, f := range t.Fields().Slice() {
			if !parameterizedBy1(f.Type, params, visited) {
				return false
			}
		}
		return true

	case types.TINTER:
		for _, f := range t.Methods().Slice() {
			if !parameterizedBy1(f.Type, params, visited) {
				return false
			}
		}
		return true

	case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64,
		types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64,
		types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR:
		return true

	case types.TUNION:
		for i := 0; i < t.NumTerms(); i++ {
			tt, _ := t.Term(i)
			if !parameterizedBy1(tt, params, visited) {
				return false
			}
		}
		return true

	default:
		base.Fatalf("bad type kind %+v", t)
		return true
	}
}

// startClosures starts creation of a closure that has the function type typ. It
// creates all the formal params and results according to the type typ. On return,
// the body and closure variables of the closure must still be filled in, and
// ir.UseClosure() called.
func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*types.Field, []*types.Field) {
	// Make a new internal function.
	fn := ir.NewClosureFunc(pos, outer != nil)
	ir.NameClosure(fn.OClosure, outer)

	// Build formal argument and return lists.
	var formalParams []*types.Field  // arguments of closure
	var formalResults []*types.Field // returns of closure
	for i := 0; i < typ.NumParams(); i++ {
		t := typ.Params().Field(i).Type
		arg := ir.NewNameAt(pos, closureSym(outer, "a", i))
		arg.Class = ir.PPARAM
		typed(t, arg)
		arg.Curfn = fn
		fn.Dcl = append(fn.Dcl, arg)
		f := types.NewField(pos, arg.Sym(), t)
		f.Nname = arg
		f.SetIsDDD(typ.Params().Field(i).IsDDD())
		formalParams = append(formalParams, f)
	}
	for i := 0; i < typ.NumResults(); i++ {
		t := typ.Results().Field(i).Type
		result := ir.NewNameAt(pos, closureSym(outer, "r", i)) // TODO: names not needed?
		result.Class = ir.PPARAMOUT
		typed(t, result)
		result.Curfn = fn
		fn.Dcl = append(fn.Dcl, result)
		f := types.NewField(pos, result.Sym(), t)
		f.Nname = result
		formalResults = append(formalResults, f)
	}

	// Build an internal function with the right signature.
	closureType := types.NewSignature(typ.Pkg(), nil, nil, formalParams, formalResults)
	typed(closureType, fn.Nname)
	typed(typ, fn.OClosure)
	fn.SetTypecheck(1)
	return fn, formalParams, formalResults

}

// closureSym returns outer.Sym().Pkg.LookupNum(prefix, n).
// If outer is nil, then types.LocalPkg is used instead.
func closureSym(outer *ir.Func, prefix string, n int) *types.Sym {
	pkg := types.LocalPkg
	if outer != nil {
		pkg = outer.Sym().Pkg
	}
	return pkg.LookupNum(prefix, n)
}

// assertToBound returns a new node that converts a node rcvr with interface type to
// the 'dst' interface type.
func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, dst *types.Type) ir.Node {
	if !dst.HasShape() {
		return typed(dst, ir.NewTypeAssertExpr(pos, rcvr, nil))
	}

	ix := findDictType(info, dst)
	assert(ix >= 0)
	rt := getDictionaryType(info, dictVar, pos, ix)
	return typed(dst, ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, rcvr, rt))
}
