1// Copyright 2021 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// This file will evolve, since we plan to do a mix of stenciling and passing 6// around dictionaries. 7 8package noder 9 10import ( 11 "cmd/compile/internal/base" 12 "cmd/compile/internal/inline" 13 "cmd/compile/internal/ir" 14 "cmd/compile/internal/objw" 15 "cmd/compile/internal/reflectdata" 16 "cmd/compile/internal/typecheck" 17 "cmd/compile/internal/types" 18 "cmd/internal/obj" 19 "cmd/internal/src" 20 "fmt" 21 "go/constant" 22) 23 24// Enable extra consistency checks. 25const doubleCheck = false 26 27func assert(p bool) { 28 base.Assert(p) 29} 30 31// For outputting debug information on dictionary format and instantiated dictionaries 32// (type arg, derived types, sub-dictionary, and itab entries). 33var infoPrintMode = false 34 35func infoPrint(format string, a ...interface{}) { 36 if infoPrintMode { 37 fmt.Printf(format, a...) 38 } 39} 40 41var geninst genInst 42 43func BuildInstantiations(preinliningMainScan bool) { 44 if geninst.instInfoMap == nil { 45 geninst.instInfoMap = make(map[*types.Sym]*instInfo) 46 } 47 geninst.buildInstantiations(preinliningMainScan) 48} 49 50// buildInstantiations scans functions for generic function calls and methods, and 51// creates the required instantiations. It also creates instantiated methods for all 52// fully-instantiated generic types that have been encountered already or new ones 53// that are encountered during the instantiation process. If preinliningMainScan is 54// true, it scans all declarations in typecheck.Target.Decls first, before scanning 55// any new instantiations created. If preinliningMainScan is false, we do not scan 56// any existing decls - we only scan method instantiations for any new 57// fully-instantiated types that we saw during inlining. 58func (g *genInst) buildInstantiations(preinliningMainScan bool) { 59 // Instantiate the methods of instantiated generic types that we have seen so far. 60 g.instantiateMethods() 61 62 if preinliningMainScan { 63 n := len(typecheck.Target.Decls) 64 for i := 0; i < n; i++ { 65 g.scanForGenCalls(typecheck.Target.Decls[i]) 66 } 67 } 68 69 // Scan all new instantiations created due to g.instantiateMethods() and the 70 // scan of current decls (if done). This loop purposely runs until no new 71 // instantiations are created. 72 for i := 0; i < len(g.newInsts); i++ { 73 g.scanForGenCalls(g.newInsts[i]) 74 } 75 76 g.finalizeSyms() 77 78 // All the instantiations and dictionaries have been created. Now go through 79 // each new instantiation and transform the various operations that need to make 80 // use of their dictionary. 81 l := len(g.newInsts) 82 for _, fun := range g.newInsts { 83 info := g.instInfoMap[fun.Sym()] 84 g.dictPass(info) 85 if !preinliningMainScan { 86 // Prepare for the round of inlining below. 87 inline.CanInline(fun.(*ir.Func)) 88 } 89 if doubleCheck { 90 ir.Visit(info.fun, func(n ir.Node) { 91 if n.Op() != ir.OCONVIFACE { 92 return 93 } 94 c := n.(*ir.ConvExpr) 95 if c.X.Type().HasShape() && !c.X.Type().IsInterface() { 96 ir.Dump("BAD FUNCTION", info.fun) 97 ir.Dump("BAD CONVERSION", c) 98 base.Fatalf("converting shape type to interface") 99 } 100 }) 101 } 102 if base.Flag.W > 1 { 103 ir.Dump(fmt.Sprintf("\ndictpass %v", info.fun), info.fun) 104 } 105 } 106 if !preinliningMainScan { 107 // Extra round of inlining for the new instantiations (only if 108 // preinliningMainScan is false, which means we have already done the 109 // main round of inlining) 110 for _, fun := range g.newInsts { 111 inline.InlineCalls(fun.(*ir.Func)) 112 // New instantiations created during inlining should run 113 // ComputeAddrTaken directly, since we are past the main pass 114 // that did ComputeAddrTaken(). We could instead do this 115 // incrementally during stenciling (for all instantiations, 116 // including main ones before inlining), since we have the 117 // type information. 118 typecheck.ComputeAddrtaken(fun.(*ir.Func).Body) 119 } 120 } 121 assert(l == len(g.newInsts)) 122 g.newInsts = nil 123} 124 125// scanForGenCalls scans a single function (or global assignment), looking for 126// references to generic functions/methods. At each such reference, it creates any 127// required instantiation and transforms the reference. 128func (g *genInst) scanForGenCalls(decl ir.Node) { 129 switch decl.Op() { 130 case ir.ODCLFUNC: 131 if decl.Type().HasTParam() { 132 // Skip any generic functions 133 return 134 } 135 // transformCall() below depends on CurFunc being set. 136 ir.CurFunc = decl.(*ir.Func) 137 138 case ir.OAS, ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV, ir.OASOP: 139 // These are all the various kinds of global assignments, 140 // whose right-hand-sides might contain a function 141 // instantiation. 142 143 default: 144 // The other possible ops at the top level are ODCLCONST 145 // and ODCLTYPE, which don't have any function 146 // instantiations. 147 return 148 } 149 150 // Search for any function references using generic function/methods. Then 151 // create the needed instantiated function if it hasn't been created yet, and 152 // change to calling that function directly. 153 modified := false 154 closureRequired := false 155 // declInfo will be non-nil exactly if we are scanning an instantiated function 156 declInfo := g.instInfoMap[decl.Sym()] 157 158 ir.Visit(decl, func(n ir.Node) { 159 if n.Op() == ir.OFUNCINST { 160 // generic F, not immediately called 161 closureRequired = true 162 } 163 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) { 164 // T.M or x.M, where T or x is generic, but not immediately 165 // called. Not necessary if the method selected is 166 // actually for an embedded interface field. 167 closureRequired = true 168 } 169 if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { 170 // We have found a function call using a generic function 171 // instantiation. 172 call := n.(*ir.CallExpr) 173 inst := call.X.(*ir.InstExpr) 174 nameNode, isMeth := g.getInstNameNode(inst) 175 targs := typecheck.TypesOf(inst.Targs) 176 st := g.getInstantiation(nameNode, targs, isMeth).fun 177 dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, nameNode, targs, isMeth) 178 if infoPrintMode { 179 dictkind := "Main dictionary" 180 if usingSubdict { 181 dictkind = "Sub-dictionary" 182 } 183 if inst.X.Op() == ir.OMETHVALUE { 184 fmt.Printf("%s in %v at generic method call: %v - %v\n", dictkind, decl, inst.X, call) 185 } else { 186 fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call) 187 } 188 } 189 190 // Transform the Call now, which changes OCALL to 191 // OCALLFUNC and does typecheckaste/assignconvfn. Do 192 // it before installing the instantiation, so we are 193 // checking against non-shape param types in 194 // typecheckaste. 195 transformCall(call) 196 197 // Replace the OFUNCINST with a direct reference to the 198 // new stenciled function 199 call.X = st.Nname 200 if inst.X.Op() == ir.OMETHVALUE { 201 // When we create an instantiation of a method 202 // call, we make it a function. So, move the 203 // receiver to be the first arg of the function 204 // call. 205 call.Args.Prepend(inst.X.(*ir.SelectorExpr).X) 206 } 207 208 // Add dictionary to argument list. 209 call.Args.Prepend(dictValue) 210 modified = true 211 } 212 if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 { 213 // Method call on a generic type, which was instantiated by stenciling. 214 // Method calls on explicitly instantiated types will have an OFUNCINST 215 // and are handled above. 216 call := n.(*ir.CallExpr) 217 meth := call.X.(*ir.SelectorExpr) 218 targs := deref(meth.Type().Recv().Type).RParams() 219 220 t := meth.X.Type() 221 baseSym := deref(t).OrigSym() 222 baseType := baseSym.Def.(*ir.Name).Type() 223 var gf *ir.Name 224 for _, m := range baseType.Methods().Slice() { 225 if meth.Sel == m.Sym { 226 gf = m.Nname.(*ir.Name) 227 break 228 } 229 } 230 231 // Transform the Call now, which changes OCALL 232 // to OCALLFUNC and does typecheckaste/assignconvfn. 233 transformCall(call) 234 235 st := g.getInstantiation(gf, targs, true).fun 236 dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) 237 // We have to be using a subdictionary, since this is 238 // a generic method call. 239 assert(usingSubdict) 240 241 // Transform to a function call, by appending the 242 // dictionary and the receiver to the args. 243 call.SetOp(ir.OCALLFUNC) 244 call.X = st.Nname 245 call.Args.Prepend(dictValue, meth.X) 246 modified = true 247 } 248 }) 249 250 // If we found a reference to a generic instantiation that wasn't an 251 // immediate call, then traverse the nodes of decl again (with 252 // EditChildren rather than Visit), where we actually change the 253 // reference to the instantiation to a closure that captures the 254 // dictionary, then does a direct call. 255 // EditChildren is more expensive than Visit, so we only do this 256 // in the infrequent case of an OFUNCINST without a corresponding 257 // call. 258 if closureRequired { 259 modified = true 260 var edit func(ir.Node) ir.Node 261 var outer *ir.Func 262 if f, ok := decl.(*ir.Func); ok { 263 outer = f 264 } 265 edit = func(x ir.Node) ir.Node { 266 if x.Op() == ir.OFUNCINST { 267 child := x.(*ir.InstExpr).X 268 if child.Op() == ir.OMETHEXPR || child.Op() == ir.OMETHVALUE { 269 // Call EditChildren on child (x.X), 270 // not x, so that we don't do 271 // buildClosure() on the 272 // METHEXPR/METHVALUE nodes as well. 273 ir.EditChildren(child, edit) 274 return g.buildClosure(outer, x) 275 } 276 } 277 ir.EditChildren(x, edit) 278 switch { 279 case x.Op() == ir.OFUNCINST: 280 return g.buildClosure(outer, x) 281 case (x.Op() == ir.OMETHEXPR || x.Op() == ir.OMETHVALUE) && 282 len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && 283 !types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): 284 return g.buildClosure(outer, x) 285 } 286 return x 287 } 288 edit(decl) 289 } 290 if base.Flag.W > 1 && modified { 291 ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl) 292 } 293 ir.CurFunc = nil 294 // We may have seen new fully-instantiated generic types while 295 // instantiating any needed functions/methods in the above 296 // function. If so, instantiate all the methods of those types 297 // (which will then lead to more function/methods to scan in the loop). 298 g.instantiateMethods() 299} 300 301// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR/OMETHVALUE 302// of generic type. outer is the containing function (or nil if closure is 303// in a global assignment instead of a function). 304func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node { 305 pos := x.Pos() 306 var target *ir.Func // target instantiated function/method 307 var dictValue ir.Node // dictionary to use 308 var rcvrValue ir.Node // receiver, if a method value 309 typ := x.Type() // type of the closure 310 var outerInfo *instInfo 311 if outer != nil { 312 outerInfo = g.instInfoMap[outer.Sym()] 313 } 314 usingSubdict := false 315 valueMethod := false 316 if x.Op() == ir.OFUNCINST { 317 inst := x.(*ir.InstExpr) 318 319 // Type arguments we're instantiating with. 320 targs := typecheck.TypesOf(inst.Targs) 321 322 // Find the generic function/method. 323 var gf *ir.Name 324 if inst.X.Op() == ir.ONAME { 325 // Instantiating a generic function call. 326 gf = inst.X.(*ir.Name) 327 } else if inst.X.Op() == ir.OMETHVALUE { 328 // Instantiating a method value x.M. 329 se := inst.X.(*ir.SelectorExpr) 330 rcvrValue = se.X 331 gf = se.Selection.Nname.(*ir.Name) 332 } else { 333 panic("unhandled") 334 } 335 336 // target is the instantiated function we're trying to call. 337 // For functions, the target expects a dictionary as its first argument. 338 // For method values, the target expects a dictionary and the receiver 339 // as its first two arguments. 340 // dictValue is the value to use for the dictionary argument. 341 target = g.getInstantiation(gf, targs, rcvrValue != nil).fun 342 dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, rcvrValue != nil) 343 if infoPrintMode { 344 dictkind := "Main dictionary" 345 if usingSubdict { 346 dictkind = "Sub-dictionary" 347 } 348 if rcvrValue == nil { 349 fmt.Printf("%s in %v for generic function value %v\n", dictkind, outer, inst.X) 350 } else { 351 fmt.Printf("%s in %v for generic method value %v\n", dictkind, outer, inst.X) 352 } 353 } 354 } else { // ir.OMETHEXPR or ir.METHVALUE 355 // Method expression T.M where T is a generic type. 356 se := x.(*ir.SelectorExpr) 357 targs := deref(se.X.Type()).RParams() 358 if len(targs) == 0 { 359 panic("bad") 360 } 361 if x.Op() == ir.OMETHVALUE { 362 rcvrValue = se.X 363 } 364 365 // se.X.Type() is the top-level type of the method expression. To 366 // correctly handle method expressions involving embedded fields, 367 // look up the generic method below using the type of the receiver 368 // of se.Selection, since that will be the type that actually has 369 // the method. 370 recv := deref(se.Selection.Type.Recv().Type) 371 if len(recv.RParams()) == 0 { 372 // The embedded type that actually has the method is not 373 // actually generic, so no need to build a closure. 374 return x 375 } 376 baseType := recv.OrigSym().Def.Type() 377 var gf *ir.Name 378 for _, m := range baseType.Methods().Slice() { 379 if se.Sel == m.Sym { 380 gf = m.Nname.(*ir.Name) 381 break 382 } 383 } 384 if !gf.Type().Recv().Type.IsPtr() { 385 // Remember if value method, so we can detect (*T).M case. 386 valueMethod = true 387 } 388 target = g.getInstantiation(gf, targs, true).fun 389 dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true) 390 if infoPrintMode { 391 dictkind := "Main dictionary" 392 if usingSubdict { 393 dictkind = "Sub-dictionary" 394 } 395 fmt.Printf("%s in %v for method expression %v\n", dictkind, outer, x) 396 } 397 } 398 399 // Build a closure to implement a function instantiation. 400 // 401 // func f[T any] (int, int) (int, int) { ...whatever... } 402 // 403 // Then any reference to f[int] not directly called gets rewritten to 404 // 405 // .dictN := ... dictionary to use ... 406 // func(a0, a1 int) (r0, r1 int) { 407 // return .inst.f[int](.dictN, a0, a1) 408 // } 409 // 410 // Similarly for method expressions, 411 // 412 // type g[T any] .... 413 // func (rcvr g[T]) f(a0, a1 int) (r0, r1 int) { ... } 414 // 415 // Any reference to g[int].f not directly called gets rewritten to 416 // 417 // .dictN := ... dictionary to use ... 418 // func(rcvr g[int], a0, a1 int) (r0, r1 int) { 419 // return .inst.g[int].f(.dictN, rcvr, a0, a1) 420 // } 421 // 422 // Also method values 423 // 424 // var x g[int] 425 // 426 // Any reference to x.f not directly called gets rewritten to 427 // 428 // .dictN := ... dictionary to use ... 429 // x2 := x 430 // func(a0, a1 int) (r0, r1 int) { 431 // return .inst.g[int].f(.dictN, x2, a0, a1) 432 // } 433 434 // Make a new internal function. 435 fn, formalParams, formalResults := startClosure(pos, outer, typ) 436 437 // This is the dictionary we want to use. 438 // It may be a constant, or it may be a dictionary acquired from the outer function's dictionary. 439 // For the latter, dictVar is a variable in the outer function's scope, set to the subdictionary 440 // read from the outer function's dictionary. 441 var dictVar *ir.Name 442 var dictAssign *ir.AssignStmt 443 if outer != nil { 444 dictVar = ir.NewNameAt(pos, typecheck.LookupNum(typecheck.LocalDictName, g.dnum)) 445 g.dnum++ 446 dictVar.Class = ir.PAUTO 447 typed(types.Types[types.TUINTPTR], dictVar) 448 dictVar.Curfn = outer 449 dictAssign = ir.NewAssignStmt(pos, dictVar, dictValue) 450 dictAssign.SetTypecheck(1) 451 dictVar.Defn = dictAssign 452 outer.Dcl = append(outer.Dcl, dictVar) 453 } 454 // assign the receiver to a temporary. 455 var rcvrVar *ir.Name 456 var rcvrAssign ir.Node 457 if rcvrValue != nil { 458 rcvrVar = ir.NewNameAt(pos, typecheck.LookupNum(".rcvr", g.dnum)) 459 g.dnum++ 460 typed(rcvrValue.Type(), rcvrVar) 461 rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue) 462 rcvrAssign.SetTypecheck(1) 463 rcvrVar.Defn = rcvrAssign 464 if outer == nil { 465 rcvrVar.Class = ir.PEXTERN 466 typecheck.Target.Decls = append(typecheck.Target.Decls, rcvrAssign) 467 typecheck.Target.Externs = append(typecheck.Target.Externs, rcvrVar) 468 } else { 469 rcvrVar.Class = ir.PAUTO 470 rcvrVar.Curfn = outer 471 outer.Dcl = append(outer.Dcl, rcvrVar) 472 } 473 } 474 475 // Build body of closure. This involves just calling the wrapped function directly 476 // with the additional dictionary argument. 477 478 // First, figure out the dictionary argument. 479 var dict2Var ir.Node 480 if usingSubdict { 481 // Capture sub-dictionary calculated in the outer function 482 dict2Var = ir.CaptureName(pos, fn, dictVar) 483 typed(types.Types[types.TUINTPTR], dict2Var) 484 } else { 485 // Static dictionary, so can be used directly in the closure 486 dict2Var = dictValue 487 } 488 // Also capture the receiver variable. 489 var rcvr2Var *ir.Name 490 if rcvrValue != nil { 491 rcvr2Var = ir.CaptureName(pos, fn, rcvrVar) 492 } 493 494 // Build arguments to call inside the closure. 495 var args []ir.Node 496 497 // First the dictionary argument. 498 args = append(args, dict2Var) 499 // Then the receiver. 500 if rcvrValue != nil { 501 args = append(args, rcvr2Var) 502 } 503 // Then all the other arguments (including receiver for method expressions). 504 for i := 0; i < typ.NumParams(); i++ { 505 if x.Op() == ir.OMETHEXPR && i == 0 { 506 // If we are doing a method expression, we need to 507 // explicitly traverse any embedded fields in the receiver 508 // argument in order to call the method instantiation. 509 arg0 := formalParams[0].Nname.(ir.Node) 510 arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(x.Pos(), ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X 511 if valueMethod && arg0.Type().IsPtr() { 512 // For handling the (*T).M case: if we have a pointer 513 // receiver after following all the embedded fields, 514 // but it's a value method, add a star operator. 515 arg0 = ir.NewStarExpr(arg0.Pos(), arg0) 516 } 517 args = append(args, arg0) 518 } else { 519 args = append(args, formalParams[i].Nname.(*ir.Name)) 520 } 521 } 522 523 // Build call itself. 524 var innerCall ir.Node = ir.NewCallExpr(pos, ir.OCALL, target.Nname, args) 525 innerCall.(*ir.CallExpr).IsDDD = typ.IsVariadic() 526 if len(formalResults) > 0 { 527 innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall}) 528 } 529 // Finish building body of closure. 530 ir.CurFunc = fn 531 // TODO: set types directly here instead of using typecheck.Stmt 532 typecheck.Stmt(innerCall) 533 ir.CurFunc = nil 534 fn.Body = []ir.Node{innerCall} 535 536 // We're all done with the captured dictionary (and receiver, for method values). 537 ir.FinishCaptureNames(pos, outer, fn) 538 539 // Make a closure referencing our new internal function. 540 c := ir.UseClosure(fn.OClosure, typecheck.Target) 541 var init []ir.Node 542 if outer != nil { 543 init = append(init, dictAssign) 544 } 545 if rcvrValue != nil { 546 init = append(init, rcvrAssign) 547 } 548 return ir.InitExpr(init, c) 549} 550 551// instantiateMethods instantiates all the methods (and associated dictionaries) of 552// all fully-instantiated generic types that have been added to typecheck.instTypeList. 553// It continues until no more types are added to typecheck.instTypeList. 554func (g *genInst) instantiateMethods() { 555 for { 556 instTypeList := typecheck.GetInstTypeList() 557 if len(instTypeList) == 0 { 558 break 559 } 560 typecheck.ClearInstTypeList() 561 for _, typ := range instTypeList { 562 assert(!typ.HasShape()) 563 // Mark runtime type as needed, since this ensures that the 564 // compiler puts out the needed DWARF symbols, when this 565 // instantiated type has a different package from the local 566 // package. 567 typecheck.NeedRuntimeType(typ) 568 // Lookup the method on the base generic type, since methods may 569 // not be set on imported instantiated types. 570 baseSym := typ.OrigSym() 571 baseType := baseSym.Def.(*ir.Name).Type() 572 for j, _ := range typ.Methods().Slice() { 573 if baseType.Methods().Slice()[j].Nointerface() { 574 typ.Methods().Slice()[j].SetNointerface(true) 575 } 576 baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) 577 // Eagerly generate the instantiations and dictionaries that implement these methods. 578 // We don't use the instantiations here, just generate them (and any 579 // further instantiations those generate, etc.). 580 // Note that we don't set the Func for any methods on instantiated 581 // types. Their signatures don't match so that would be confusing. 582 // Direct method calls go directly to the instantiations, implemented above. 583 // Indirect method calls use wrappers generated in reflectcall. Those wrappers 584 // will use these instantiations if they are needed (for interface tables or reflection). 585 _ = g.getInstantiation(baseNname, typ.RParams(), true) 586 _ = g.getDictionarySym(baseNname, typ.RParams(), true) 587 } 588 } 589 } 590} 591 592// getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated. 593func (g *genInst) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) { 594 if meth, ok := inst.X.(*ir.SelectorExpr); ok { 595 return meth.Selection.Nname.(*ir.Name), true 596 } else { 597 return inst.X.(*ir.Name), false 598 } 599} 600 601// getDictOrSubdict returns, for a method/function call or reference (node n) in an 602// instantiation (described by instInfo), a node which is accessing a sub-dictionary 603// or main/static dictionary, as needed, and also returns a boolean indicating if a 604// sub-dictionary was accessed. nameNode is the particular function or method being 605// called/referenced, and targs are the type arguments. 606func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Name, targs []*types.Type, isMeth bool) (ir.Node, bool) { 607 var dict ir.Node 608 usingSubdict := false 609 if declInfo != nil { 610 entry := -1 611 for i, de := range declInfo.dictInfo.subDictCalls { 612 if n == de { 613 entry = declInfo.dictInfo.startSubDict + i 614 break 615 } 616 } 617 // If the entry is not found, it may be that this node did not have 618 // any type args that depend on type params, so we need a main 619 // dictionary, not a sub-dictionary. 620 if entry >= 0 { 621 dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictInfo.dictLen) 622 usingSubdict = true 623 } 624 } 625 if !usingSubdict { 626 dict = g.getDictionaryValue(n.Pos(), nameNode, targs, isMeth) 627 } 628 return dict, usingSubdict 629} 630 631// checkFetchBody checks if a generic body can be fetched, but hasn't been loaded 632// yet. If so, it imports the body. 633func checkFetchBody(nameNode *ir.Name) { 634 if nameNode.Func.Body == nil && nameNode.Func.Inl != nil { 635 // If there is no body yet but Func.Inl exists, then we can 636 // import the whole generic body. 637 assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg) 638 typecheck.ImportBody(nameNode.Func) 639 assert(nameNode.Func.Inl.Body != nil) 640 nameNode.Func.Body = nameNode.Func.Inl.Body 641 nameNode.Func.Dcl = nameNode.Func.Inl.Dcl 642 } 643} 644 645// getInstantiation gets the instantiantion and dictionary of the function or method nameNode 646// with the type arguments shapes. If the instantiated function is not already 647// cached, then it calls genericSubst to create the new instantiation. 648func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo { 649 if nameNode.Func == nil { 650 // If nameNode.Func is nil, this must be a reference to a method of 651 // an imported instantiated type. We will have already called 652 // g.instantiateMethods() on the fully-instantiated type, so 653 // g.instInfoMap[sym] will be non-nil below. 654 rcvr := nameNode.Type().Recv() 655 if rcvr == nil || !deref(rcvr.Type).IsFullyInstantiated() { 656 base.FatalfAt(nameNode.Pos(), "Unexpected function instantiation %v with no body", nameNode) 657 } 658 } else { 659 checkFetchBody(nameNode) 660 } 661 662 // Convert any non-shape type arguments to their shape, so we can reduce the 663 // number of instantiations we have to generate. You can actually have a mix 664 // of shape and non-shape arguments, because of inferred or explicitly 665 // specified concrete type args. 666 s1 := make([]*types.Type, len(shapes)) 667 for i, t := range shapes { 668 if !t.IsShape() { 669 s1[i] = typecheck.Shapify(t, i) 670 } else { 671 // Already a shape, but make sure it has the correct index. 672 s1[i] = typecheck.Shapify(shapes[i].Underlying(), i) 673 } 674 } 675 shapes = s1 676 677 sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, false, isMeth) 678 info := g.instInfoMap[sym] 679 if info == nil { 680 // If instantiation doesn't exist yet, create it and add 681 // to the list of decls. 682 info = &instInfo{ 683 dictInfo: &dictInfo{}, 684 } 685 info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type) 686 687 if sym.Def != nil { 688 // This instantiation must have been imported from another 689 // package (because it was needed for inlining), so we should 690 // not re-generate it and have conflicting definitions for the 691 // symbol (issue #50121). It will have already gone through the 692 // dictionary transformations of dictPass, so we don't actually 693 // need the info.dictParam and info.shapeToBound info filled in 694 // below. We just set the imported instantiation as info.fun. 695 assert(sym.Pkg != types.LocalPkg) 696 info.fun = sym.Def.(*ir.Name).Func 697 assert(info.fun != nil) 698 g.instInfoMap[sym] = info 699 return info 700 } 701 702 // genericSubst fills in info.dictParam and info.shapeToBound. 703 st := g.genericSubst(sym, nameNode, shapes, isMeth, info) 704 info.fun = st 705 g.instInfoMap[sym] = info 706 707 // getInstInfo fills in info.dictInfo. 708 g.getInstInfo(st, shapes, info) 709 if base.Flag.W > 1 { 710 ir.Dump(fmt.Sprintf("\nstenciled %v", st), st) 711 } 712 713 // This ensures that the linker drops duplicates of this instantiation. 714 // All just works! 715 st.SetDupok(true) 716 typecheck.Target.Decls = append(typecheck.Target.Decls, st) 717 g.newInsts = append(g.newInsts, st) 718 } 719 return info 720} 721 722// Struct containing info needed for doing the substitution as we create the 723// instantiation of a generic function with specified type arguments. 724type subster struct { 725 g *genInst 726 isMethod bool // If a method is being instantiated 727 newf *ir.Func // Func node for the new stenciled function 728 ts typecheck.Tsubster 729 info *instInfo // Place to put extra info in the instantiation 730 731 // Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n 732 defnMap map[ir.Node][]**ir.Name 733} 734 735// genericSubst returns a new function with name newsym. The function is an 736// instantiation of a generic function or method specified by namedNode with type 737// args shapes. For a method with a generic receiver, it returns an instantiated 738// function type where the receiver becomes the first parameter. For either a generic 739// method or function, a dictionary parameter is the added as the very first 740// parameter. genericSubst fills in info.dictParam and info.shapeToBound. 741func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func { 742 var tparams []*types.Type 743 if isMethod { 744 // Get the type params from the method receiver (after skipping 745 // over any pointer) 746 recvType := nameNode.Type().Recv().Type 747 recvType = deref(recvType) 748 tparams = recvType.RParams() 749 } else { 750 fields := nameNode.Type().TParams().Fields().Slice() 751 tparams = make([]*types.Type, len(fields)) 752 for i, f := range fields { 753 tparams[i] = f.Type 754 } 755 } 756 gf := nameNode.Func 757 // Pos of the instantiated function is same as the generic function 758 newf := ir.NewFunc(gf.Pos()) 759 newf.Pragma = gf.Pragma // copy over pragmas from generic function to stenciled implementation. 760 newf.Nname = ir.NewNameAt(gf.Pos(), newsym) 761 newf.Nname.Func = newf 762 newf.Nname.Defn = newf 763 newsym.Def = newf.Nname 764 savef := ir.CurFunc 765 // transformCall/transformReturn (called during stenciling of the body) 766 // depend on ir.CurFunc being set. 767 ir.CurFunc = newf 768 769 assert(len(tparams) == len(shapes)) 770 771 subst := &subster{ 772 g: g, 773 isMethod: isMethod, 774 newf: newf, 775 info: info, 776 ts: typecheck.Tsubster{ 777 Tparams: tparams, 778 Targs: shapes, 779 Vars: make(map[*ir.Name]*ir.Name), 780 }, 781 defnMap: make(map[ir.Node][]**ir.Name), 782 } 783 784 newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) 785 786 // Create the needed dictionary param 787 dictionarySym := newsym.Pkg.Lookup(typecheck.LocalDictName) 788 dictionaryType := types.Types[types.TUINTPTR] 789 dictionaryName := ir.NewNameAt(gf.Pos(), dictionarySym) 790 typed(dictionaryType, dictionaryName) 791 dictionaryName.Class = ir.PPARAM 792 dictionaryName.Curfn = newf 793 newf.Dcl = append(newf.Dcl, dictionaryName) 794 for _, n := range gf.Dcl { 795 if n.Sym().Name == typecheck.LocalDictName { 796 panic("already has dictionary") 797 } 798 newf.Dcl = append(newf.Dcl, subst.localvar(n)) 799 } 800 dictionaryArg := types.NewField(gf.Pos(), dictionarySym, dictionaryType) 801 dictionaryArg.Nname = dictionaryName 802 info.dictParam = dictionaryName 803 804 // We add the dictionary as the first parameter in the function signature. 805 // We also transform a method type to the corresponding function type 806 // (make the receiver be the next parameter after the dictionary). 807 oldt := nameNode.Type() 808 var args []*types.Field 809 args = append(args, dictionaryArg) 810 args = append(args, oldt.Recvs().FieldSlice()...) 811 args = append(args, oldt.Params().FieldSlice()...) 812 813 // Replace the types in the function signature via subst.fields. 814 // Ugly: also, we have to insert the Name nodes of the parameters/results into 815 // the function type. The current function type has no Nname fields set, 816 // because it came via conversion from the types2 type. 817 newt := types.NewSignature(oldt.Pkg(), nil, nil, 818 subst.fields(ir.PPARAM, args, newf.Dcl), 819 subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl)) 820 821 typed(newt, newf.Nname) 822 ir.MarkFunc(newf.Nname) 823 newf.SetTypecheck(1) 824 825 // Make sure name/type of newf is set before substituting the body. 826 newf.Body = subst.list(gf.Body) 827 if len(newf.Body) == 0 { 828 // Ensure the body is nonempty, for issue 49524. 829 // TODO: have some other way to detect the difference between 830 // a function declared with no body, vs. one with an empty body? 831 newf.Body = append(newf.Body, ir.NewBlockStmt(gf.Pos(), nil)) 832 } 833 834 if len(subst.defnMap) > 0 { 835 base.Fatalf("defnMap is not empty") 836 } 837 838 for i, tp := range tparams { 839 info.dictInfo.shapeToBound[shapes[i]] = subst.ts.Typ(tp.Bound()) 840 } 841 842 ir.CurFunc = savef 843 844 return subst.newf 845} 846 847// localvar creates a new name node for the specified local variable and enters it 848// in subst.vars. It substitutes type arguments for type parameters in the type of 849// name as needed. 850func (subst *subster) localvar(name *ir.Name) *ir.Name { 851 m := ir.NewNameAt(name.Pos(), name.Sym()) 852 if name.IsClosureVar() { 853 m.SetIsClosureVar(true) 854 } 855 m.SetType(subst.ts.Typ(name.Type())) 856 m.BuiltinOp = name.BuiltinOp 857 m.Curfn = subst.newf 858 m.Class = name.Class 859 assert(name.Class != ir.PEXTERN && name.Class != ir.PFUNC) 860 m.Func = name.Func 861 subst.ts.Vars[name] = m 862 m.SetTypecheck(1) 863 m.DictIndex = name.DictIndex 864 if name.Defn != nil { 865 if name.Defn.Op() == ir.ONAME { 866 // This is a closure variable, so its Defn is the outer 867 // captured variable, which has already been substituted. 868 m.Defn = subst.node(name.Defn) 869 } else { 870 // The other values of Defn are nodes in the body of the 871 // function, so just remember the mapping so we can set Defn 872 // properly in node() when we create the new body node. We 873 // always call localvar() on all the local variables before 874 // we substitute the body. 875 slice := subst.defnMap[name.Defn] 876 subst.defnMap[name.Defn] = append(slice, &m) 877 } 878 } 879 if name.Outer != nil { 880 m.Outer = subst.node(name.Outer).(*ir.Name) 881 } 882 883 return m 884} 885 886// getDictionaryEntry gets the i'th entry in the dictionary dict. 887func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node { 888 // Convert dictionary to *[N]uintptr 889 // All entries in the dictionary are pointers. They all point to static data, though, so we 890 // treat them as uintptrs so the GC doesn't need to keep track of them. 891 d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], dict) 892 d.SetTypecheck(1) 893 d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(size)).PtrTo(), d) 894 d.SetTypecheck(1) 895 types.CheckSize(d.Type().Elem()) 896 897 // Load entry i out of the dictionary. 898 deref := ir.NewStarExpr(pos, d) 899 typed(d.Type().Elem(), deref) 900 idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), dict) // TODO: what to set orig to? 901 typed(types.Types[types.TUINTPTR], idx) 902 r := ir.NewIndexExpr(pos, deref, idx) 903 typed(types.Types[types.TUINTPTR], r) 904 return r 905} 906 907// getDictionaryType returns a *runtime._type from the dictionary entry i (which 908// refers to a type param or a derived type that uses type params). It uses the 909// specified dictionary dictParam, rather than the one in info.dictParam. 910func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int) ir.Node { 911 if i < 0 || i >= info.dictInfo.startSubDict { 912 base.Fatalf(fmt.Sprintf("bad dict index %d", i)) 913 } 914 915 r := getDictionaryEntry(pos, info.dictParam, i, info.dictInfo.startSubDict) 916 // change type of retrieved dictionary entry to *byte, which is the 917 // standard typing of a *runtime._type in the compiler 918 typed(types.Types[types.TUINT8].PtrTo(), r) 919 return r 920} 921 922// node is like DeepCopy(), but substitutes ONAME nodes based on subst.ts.vars, and 923// also descends into closures. It substitutes type arguments for type parameters in 924// all the new nodes and does the transformations that were delayed on the generic 925// function. 926func (subst *subster) node(n ir.Node) ir.Node { 927 // Use closure to capture all state needed by the ir.EditChildren argument. 928 var edit func(ir.Node) ir.Node 929 edit = func(x ir.Node) ir.Node { 930 // Analogous to ir.SetPos() at beginning of typecheck.typecheck() - 931 // allows using base.Pos during the transform functions, just like 932 // the tc*() functions. 933 ir.SetPos(x) 934 switch x.Op() { 935 case ir.OTYPE: 936 return ir.TypeNode(subst.ts.Typ(x.Type())) 937 938 case ir.ONAME: 939 if v := subst.ts.Vars[x.(*ir.Name)]; v != nil { 940 return v 941 } 942 if ir.IsBlank(x) { 943 // Special case, because a blank local variable is 944 // not in the fn.Dcl list. 945 m := ir.NewNameAt(x.Pos(), ir.BlankNode.Sym()) 946 return typed(subst.ts.Typ(x.Type()), m) 947 } 948 return x 949 case ir.ONONAME: 950 // This handles the identifier in a type switch guard 951 fallthrough 952 case ir.OLITERAL, ir.ONIL: 953 if x.Sym() != nil { 954 return x 955 } 956 } 957 m := ir.Copy(x) 958 959 slice, ok := subst.defnMap[x] 960 if ok { 961 // We just copied a non-ONAME node which was the Defn value 962 // of a local variable. Set the Defn value of the copied 963 // local variable to this new Defn node. 964 for _, ptr := range slice { 965 (*ptr).Defn = m 966 } 967 delete(subst.defnMap, x) 968 } 969 970 if _, isExpr := m.(ir.Expr); isExpr { 971 t := x.Type() 972 if t == nil { 973 // Check for known cases where t can be nil (call 974 // that has no return values, and key expressions) 975 // and otherwise cause a fatal error. 976 _, isCallExpr := m.(*ir.CallExpr) 977 _, isStructKeyExpr := m.(*ir.StructKeyExpr) 978 _, isKeyExpr := m.(*ir.KeyExpr) 979 if !isCallExpr && !isStructKeyExpr && !isKeyExpr && x.Op() != ir.OPANIC && 980 x.Op() != ir.OCLOSE { 981 base.FatalfAt(m.Pos(), "Nil type for %v", x) 982 } 983 } else if x.Op() != ir.OCLOSURE { 984 m.SetType(subst.ts.Typ(x.Type())) 985 } 986 } 987 988 ir.EditChildren(m, edit) 989 990 m.SetTypecheck(1) 991 992 // Do the transformations that we delayed on the generic function 993 // node, now that we have substituted in the type args. 994 switch x.Op() { 995 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: 996 transformCompare(m.(*ir.BinaryExpr)) 997 998 case ir.OSLICE, ir.OSLICE3: 999 transformSlice(m.(*ir.SliceExpr)) 1000 1001 case ir.OADD: 1002 m = transformAdd(m.(*ir.BinaryExpr)) 1003 1004 case ir.OINDEX: 1005 transformIndex(m.(*ir.IndexExpr)) 1006 1007 case ir.OAS2: 1008 as2 := m.(*ir.AssignListStmt) 1009 transformAssign(as2, as2.Lhs, as2.Rhs) 1010 1011 case ir.OAS: 1012 as := m.(*ir.AssignStmt) 1013 if as.Y != nil { 1014 // transformAssign doesn't handle the case 1015 // of zeroing assignment of a dcl (rhs[0] is nil). 1016 lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y} 1017 transformAssign(as, lhs, rhs) 1018 as.X, as.Y = lhs[0], rhs[0] 1019 } 1020 1021 case ir.OASOP: 1022 as := m.(*ir.AssignOpStmt) 1023 transformCheckAssign(as, as.X) 1024 1025 case ir.ORETURN: 1026 transformReturn(m.(*ir.ReturnStmt)) 1027 1028 case ir.OSEND: 1029 transformSend(m.(*ir.SendStmt)) 1030 1031 case ir.OSELECT: 1032 transformSelect(m.(*ir.SelectStmt)) 1033 1034 case ir.OCOMPLIT: 1035 transformCompLit(m.(*ir.CompLitExpr)) 1036 1037 case ir.OADDR: 1038 transformAddr(m.(*ir.AddrExpr)) 1039 1040 case ir.OLITERAL: 1041 t := m.Type() 1042 if t != x.Type() { 1043 // types2 will give us a constant with a type T, 1044 // if an untyped constant is used with another 1045 // operand of type T (in a provably correct way). 1046 // When we substitute in the type args during 1047 // stenciling, we now know the real type of the 1048 // constant. We may then need to change the 1049 // BasicLit.val to be the correct type (e.g. 1050 // convert an int64Val constant to a floatVal 1051 // constant). 1052 m.SetType(types.UntypedInt) // use any untyped type for DefaultLit to work 1053 m = typecheck.DefaultLit(m, t) 1054 } 1055 1056 case ir.OXDOT: 1057 // Finish the transformation of an OXDOT, unless this was a 1058 // bound call (a direct call on a type param). A bound call 1059 // will be transformed during the dictPass. Otherwise, m 1060 // will be transformed to an OMETHVALUE node. It will be 1061 // transformed to an ODOTMETH or ODOTINTER node if we find in 1062 // the OCALL case below that the method value is actually 1063 // called. 1064 mse := m.(*ir.SelectorExpr) 1065 if src := mse.X.Type(); !src.IsShape() { 1066 transformDot(mse, false) 1067 } 1068 1069 case ir.OCALL: 1070 call := m.(*ir.CallExpr) 1071 switch call.X.Op() { 1072 case ir.OTYPE: 1073 // Transform the conversion, now that we know the 1074 // type argument. 1075 m = transformConvCall(call) 1076 // CONVIFACE transformation was already done in noder2 1077 assert(m.Op() != ir.OCONVIFACE) 1078 1079 case ir.OMETHVALUE, ir.OMETHEXPR: 1080 // Redo the transformation of OXDOT, now that we 1081 // know the method value is being called. Then 1082 // transform the call. 1083 call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) 1084 transformDot(call.X.(*ir.SelectorExpr), true) 1085 transformCall(call) 1086 1087 case ir.ODOT, ir.ODOTPTR: 1088 // An OXDOT for a generic receiver was resolved to 1089 // an access to a field which has a function 1090 // value. Transform the call to that function, now 1091 // that the OXDOT was resolved. 1092 transformCall(call) 1093 1094 case ir.ONAME: 1095 name := call.X.Name() 1096 if name.BuiltinOp != ir.OXXX { 1097 switch name.BuiltinOp { 1098 case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: 1099 // Transform these builtins now that we 1100 // know the type of the args. 1101 m = transformBuiltin(call) 1102 default: 1103 base.FatalfAt(call.Pos(), "Unexpected builtin op") 1104 } 1105 } else { 1106 // This is the case of a function value that was a 1107 // type parameter (implied to be a function via a 1108 // structural constraint) which is now resolved. 1109 transformCall(call) 1110 } 1111 1112 case ir.OFUNCINST: 1113 // A call with an OFUNCINST will get transformed 1114 // in stencil() once we have created & attached the 1115 // instantiation to be called. 1116 // We must transform the arguments of the call now, though, 1117 // so that any needed CONVIFACE nodes are exposed, 1118 // so the dictionary format is correct. 1119 transformEarlyCall(call) 1120 1121 case ir.OXDOT: 1122 // This is the case of a bound call on a typeparam, 1123 // which will be handled in the dictPass. 1124 // As with OFUNCINST, we must transform the arguments of the call now, 1125 // so any needed CONVIFACE nodes are exposed. 1126 transformEarlyCall(call) 1127 1128 case ir.ODOTTYPE, ir.ODOTTYPE2: 1129 // These are DOTTYPEs that could get transformed into 1130 // ODYNAMIC DOTTYPEs by the dict pass. 1131 1132 default: 1133 // Transform a call for all other values of 1134 // call.X.Op() that don't require any special 1135 // handling. 1136 transformCall(call) 1137 1138 } 1139 1140 case ir.OCLOSURE: 1141 // We're going to create a new closure from scratch, so clear m 1142 // to avoid using the ir.Copy by accident until we reassign it. 1143 m = nil 1144 1145 x := x.(*ir.ClosureExpr) 1146 // Need to duplicate x.Func.Nname, x.Func.Dcl, x.Func.ClosureVars, and 1147 // x.Func.Body. 1148 oldfn := x.Func 1149 newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf != nil) 1150 ir.NameClosure(newfn.OClosure, subst.newf) 1151 1152 saveNewf := subst.newf 1153 ir.CurFunc = newfn 1154 subst.newf = newfn 1155 newfn.Dcl = subst.namelist(oldfn.Dcl) 1156 1157 // Make a closure variable for the dictionary of the 1158 // containing function. 1159 cdict := ir.CaptureName(oldfn.Pos(), newfn, subst.info.dictParam) 1160 typed(types.Types[types.TUINTPTR], cdict) 1161 ir.FinishCaptureNames(oldfn.Pos(), saveNewf, newfn) 1162 newfn.ClosureVars = append(newfn.ClosureVars, subst.namelist(oldfn.ClosureVars)...) 1163 1164 // Copy that closure variable to a local one. 1165 // Note: this allows the dictionary to be captured by child closures. 1166 // See issue 47723. 1167 ldict := ir.NewNameAt(x.Pos(), newfn.Sym().Pkg.Lookup(typecheck.LocalDictName)) 1168 typed(types.Types[types.TUINTPTR], ldict) 1169 ldict.Class = ir.PAUTO 1170 ldict.Curfn = newfn 1171 newfn.Dcl = append(newfn.Dcl, ldict) 1172 as := ir.NewAssignStmt(x.Pos(), ldict, cdict) 1173 as.SetTypecheck(1) 1174 newfn.Body.Append(as) 1175 1176 // Create inst info for the instantiated closure. The dict 1177 // param is the closure variable for the dictionary of the 1178 // outer function. Since the dictionary is shared, use the 1179 // same dictInfo. 1180 cinfo := &instInfo{ 1181 fun: newfn, 1182 dictParam: ldict, 1183 dictInfo: subst.info.dictInfo, 1184 } 1185 subst.g.instInfoMap[newfn.Nname.Sym()] = cinfo 1186 1187 typed(subst.ts.Typ(oldfn.Nname.Type()), newfn.Nname) 1188 typed(newfn.Nname.Type(), newfn.OClosure) 1189 newfn.SetTypecheck(1) 1190 1191 outerinfo := subst.info 1192 subst.info = cinfo 1193 // Make sure type of closure function is set before doing body. 1194 newfn.Body.Append(subst.list(oldfn.Body)...) 1195 subst.info = outerinfo 1196 subst.newf = saveNewf 1197 ir.CurFunc = saveNewf 1198 1199 m = ir.UseClosure(newfn.OClosure, typecheck.Target) 1200 subst.g.newInsts = append(subst.g.newInsts, m.(*ir.ClosureExpr).Func) 1201 m.(*ir.ClosureExpr).SetInit(subst.list(x.Init())) 1202 1203 } 1204 return m 1205 } 1206 1207 return edit(n) 1208} 1209 1210// dictPass takes a function instantiation and does the transformations on the 1211// operations that need to make use of the dictionary param. 1212func (g *genInst) dictPass(info *instInfo) { 1213 savef := ir.CurFunc 1214 ir.CurFunc = info.fun 1215 1216 var edit func(ir.Node) ir.Node 1217 edit = func(m ir.Node) ir.Node { 1218 ir.EditChildren(m, edit) 1219 1220 switch m.Op() { 1221 case ir.OCLOSURE: 1222 newf := m.(*ir.ClosureExpr).Func 1223 ir.CurFunc = newf 1224 outerinfo := info 1225 info = g.instInfoMap[newf.Nname.Sym()] 1226 1227 body := newf.Body 1228 for i, n := range body { 1229 body[i] = edit(n) 1230 } 1231 1232 info = outerinfo 1233 ir.CurFunc = info.fun 1234 1235 case ir.OXDOT: 1236 mse := m.(*ir.SelectorExpr) 1237 src := mse.X.Type() 1238 assert(src.IsShape()) 1239 1240 // The only dot on a shape type value are methods. 1241 if mse.X.Op() == ir.OTYPE { 1242 // Method expression T.M 1243 m = g.buildClosure2(info, m) 1244 // No need for transformDot - buildClosure2 has already 1245 // transformed to OCALLINTER/ODOTINTER. 1246 } else { 1247 // Implement x.M as a conversion-to-bound-interface 1248 // 1) convert x to the bound interface 1249 // 2) call M on that interface 1250 dst := info.dictInfo.shapeToBound[m.(*ir.SelectorExpr).X.Type()] 1251 if src.IsInterface() { 1252 // If type arg is an interface (unusual case), 1253 // we do a type assert to the type bound. 1254 mse.X = assertToBound(info, info.dictParam, m.Pos(), mse.X, dst) 1255 } else { 1256 mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst) 1257 } 1258 transformDot(mse, false) 1259 } 1260 case ir.OCALL: 1261 call := m.(*ir.CallExpr) 1262 op := call.X.Op() 1263 if op == ir.OMETHVALUE { 1264 // Redo the transformation of OXDOT, now that we 1265 // know the method value is being called. 1266 call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) 1267 transformDot(call.X.(*ir.SelectorExpr), true) 1268 } 1269 transformCall(call) 1270 1271 case ir.OCONVIFACE: 1272 if m.Type().IsEmptyInterface() && m.(*ir.ConvExpr).X.Type().IsEmptyInterface() { 1273 // Was T->interface{}, after stenciling it is now interface{}->interface{}. 1274 // No longer need the conversion. See issue 48276. 1275 m.(*ir.ConvExpr).SetOp(ir.OCONVNOP) 1276 break 1277 } 1278 mce := m.(*ir.ConvExpr) 1279 // Note: x's argument is still typed as a type parameter. 1280 // m's argument now has an instantiated type. 1281 if mce.X.Type().HasShape() || (mce.X.Type().IsInterface() && m.Type().HasShape()) { 1282 m = convertUsingDictionary(info, info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, m, m.Type()) 1283 } 1284 case ir.ODOTTYPE, ir.ODOTTYPE2: 1285 if !m.Type().HasShape() { 1286 break 1287 } 1288 dt := m.(*ir.TypeAssertExpr) 1289 var rt ir.Node 1290 if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() { 1291 ix := findDictType(info, m.Type()) 1292 assert(ix >= 0) 1293 rt = getDictionaryType(info, info.dictParam, dt.Pos(), ix) 1294 } else { 1295 // nonempty interface to noninterface. Need an itab. 1296 ix := -1 1297 for i, ic := range info.dictInfo.itabConvs { 1298 if ic == m { 1299 ix = info.dictInfo.startItabConv + i 1300 break 1301 } 1302 } 1303 assert(ix >= 0) 1304 rt = getDictionaryEntry(dt.Pos(), info.dictParam, ix, info.dictInfo.dictLen) 1305 } 1306 op := ir.ODYNAMICDOTTYPE 1307 if m.Op() == ir.ODOTTYPE2 { 1308 op = ir.ODYNAMICDOTTYPE2 1309 } 1310 m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rt) 1311 m.SetType(dt.Type()) 1312 m.SetTypecheck(1) 1313 case ir.OCASE: 1314 if _, ok := m.(*ir.CommClause); ok { 1315 // This is not a type switch. TODO: Should we use an OSWITCH case here instead of OCASE? 1316 break 1317 } 1318 m := m.(*ir.CaseClause) 1319 for i, c := range m.List { 1320 if c.Op() == ir.OTYPE && c.Type().HasShape() { 1321 // Use a *runtime._type for the dynamic type. 1322 ix := findDictType(info, m.List[i].Type()) 1323 assert(ix >= 0) 1324 dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen)) 1325 1326 // For type switch from nonempty interfaces to non-interfaces, we need an itab as well. 1327 if !m.List[i].Type().IsInterface() { 1328 if _, ok := info.dictInfo.type2switchType[m.List[i]]; ok { 1329 // Type switch from nonempty interface. We need a *runtime.itab 1330 // for the dynamic type. 1331 ix := -1 1332 for j, ic := range info.dictInfo.itabConvs { 1333 if ic == m.List[i] { 1334 ix = info.dictInfo.startItabConv + j 1335 break 1336 } 1337 } 1338 assert(ix >= 0) 1339 dt.ITab = getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen) 1340 } 1341 } 1342 typed(m.List[i].Type(), dt) 1343 m.List[i] = dt 1344 } 1345 } 1346 1347 } 1348 return m 1349 } 1350 edit(info.fun) 1351 ir.CurFunc = savef 1352} 1353 1354// findDictType looks for type t in the typeparams or derived types in the generic 1355// function info.gfInfo. This will indicate the dictionary entry with the 1356// correct concrete type for the associated instantiated function. 1357func findDictType(info *instInfo, t *types.Type) int { 1358 for i, dt := range info.dictInfo.shapeParams { 1359 if dt == t { 1360 return i 1361 } 1362 } 1363 for i, dt := range info.dictInfo.derivedTypes { 1364 if types.IdenticalStrict(dt, t) { 1365 return i + len(info.dictInfo.shapeParams) 1366 } 1367 } 1368 return -1 1369} 1370 1371// convertUsingDictionary converts instantiated value v (type v.Type()) to an interface 1372// type dst, by returning a new set of nodes that make use of a dictionary entry. in is the 1373// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the 1374// conversion. 1375func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node { 1376 assert(v.Type().HasShape() || v.Type().IsInterface() && in.Type().HasShape()) 1377 assert(dst.IsInterface()) 1378 1379 if v.Type().IsInterface() { 1380 // Converting from an interface. The shape-ness of the source doesn't really matter, as 1381 // we'll be using the concrete type from the first interface word. 1382 if dst.IsEmptyInterface() { 1383 // Converting I2E. OCONVIFACE does that for us, and doesn't depend 1384 // on what the empty interface was instantiated with. No dictionary entry needed. 1385 v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v) 1386 v.SetTypecheck(1) 1387 return v 1388 } 1389 if !in.Type().HasShape() { 1390 // Regular OCONVIFACE works if the destination isn't parameterized. 1391 v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v) 1392 v.SetTypecheck(1) 1393 return v 1394 } 1395 1396 // We get the destination interface type from the dictionary and the concrete 1397 // type from the argument's itab. Call runtime.convI2I to get the new itab. 1398 tmp := typecheck.Temp(v.Type()) 1399 as := ir.NewAssignStmt(pos, tmp, v) 1400 as.SetTypecheck(1) 1401 itab := ir.NewUnaryExpr(pos, ir.OITAB, tmp) 1402 typed(types.Types[types.TUINTPTR].PtrTo(), itab) 1403 idata := ir.NewUnaryExpr(pos, ir.OIDATA, tmp) 1404 typed(types.Types[types.TUNSAFEPTR], idata) 1405 1406 fn := typecheck.LookupRuntime("convI2I") 1407 fn.SetTypecheck(1) 1408 types.CalcSize(fn.Type()) 1409 call := ir.NewCallExpr(pos, ir.OCALLFUNC, fn, nil) 1410 typed(types.Types[types.TUINT8].PtrTo(), call) 1411 ix := findDictType(info, in.Type()) 1412 assert(ix >= 0) 1413 inter := getDictionaryType(info, dictParam, pos, ix) 1414 call.Args = []ir.Node{inter, itab} 1415 i := ir.NewBinaryExpr(pos, ir.OEFACE, call, idata) 1416 typed(dst, i) 1417 i.PtrInit().Append(as) 1418 return i 1419 } 1420 1421 var rt ir.Node 1422 if !dst.IsEmptyInterface() { 1423 // We should have an itab entry in the dictionary. Using this itab 1424 // will be more efficient than converting to an empty interface first 1425 // and then type asserting to dst. 1426 ix := -1 1427 for i, ic := range info.dictInfo.itabConvs { 1428 if ic == in { 1429 ix = info.dictInfo.startItabConv + i 1430 break 1431 } 1432 } 1433 assert(ix >= 0) 1434 rt = getDictionaryEntry(pos, dictParam, ix, info.dictInfo.dictLen) 1435 } else { 1436 ix := findDictType(info, v.Type()) 1437 assert(ix >= 0) 1438 // Load the actual runtime._type of the type parameter from the dictionary. 1439 rt = getDictionaryType(info, dictParam, pos, ix) 1440 } 1441 1442 // Figure out what the data field of the interface will be. 1443 data := ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v) 1444 typed(types.Types[types.TUNSAFEPTR], data) 1445 1446 // Build an interface from the type and data parts. 1447 var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data) 1448 typed(dst, i) 1449 return i 1450} 1451 1452func (subst *subster) namelist(l []*ir.Name) []*ir.Name { 1453 s := make([]*ir.Name, len(l)) 1454 for i, n := range l { 1455 s[i] = subst.localvar(n) 1456 } 1457 return s 1458} 1459 1460func (subst *subster) list(l []ir.Node) []ir.Node { 1461 s := make([]ir.Node, len(l)) 1462 for i, n := range l { 1463 s[i] = subst.node(n) 1464 } 1465 return s 1466} 1467 1468// fields sets the Nname field for the Field nodes inside a type signature, based 1469// on the corresponding in/out parameters in dcl. It depends on the in and out 1470// parameters being in order in dcl. 1471func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir.Name) []*types.Field { 1472 // Find the starting index in dcl of declarations of the class (either 1473 // PPARAM or PPARAMOUT). 1474 var i int 1475 for i = range dcl { 1476 if dcl[i].Class == class { 1477 break 1478 } 1479 } 1480 1481 // Create newfields nodes that are copies of the oldfields nodes, but 1482 // with substitution for any type params, and with Nname set to be the node in 1483 // Dcl for the corresponding PPARAM or PPARAMOUT. 1484 newfields := make([]*types.Field, len(oldfields)) 1485 for j := range oldfields { 1486 newfields[j] = oldfields[j].Copy() 1487 newfields[j].Type = subst.ts.Typ(oldfields[j].Type) 1488 // A PPARAM field will be missing from dcl if its name is 1489 // unspecified or specified as "_". So, we compare the dcl sym 1490 // with the field sym (or sym of the field's Nname node). (Unnamed 1491 // results still have a name like ~r2 in their Nname node.) If 1492 // they don't match, this dcl (if there is one left) must apply to 1493 // a later field. 1494 if i < len(dcl) && (dcl[i].Sym() == oldfields[j].Sym || 1495 (oldfields[j].Nname != nil && dcl[i].Sym() == oldfields[j].Nname.Sym())) { 1496 newfields[j].Nname = dcl[i] 1497 i++ 1498 } 1499 } 1500 return newfields 1501} 1502 1503// deref does a single deref of type t, if it is a pointer type. 1504func deref(t *types.Type) *types.Type { 1505 if t.IsPtr() { 1506 return t.Elem() 1507 } 1508 return t 1509} 1510 1511// markTypeUsed marks type t as used in order to help avoid dead-code elimination of 1512// needed methods. 1513func markTypeUsed(t *types.Type, lsym *obj.LSym) { 1514 if t.IsInterface() { 1515 return 1516 } 1517 // TODO: This is somewhat overkill, we really only need it 1518 // for types that are put into interfaces. 1519 // Note: this relocation is also used in cmd/link/internal/ld/dwarf.go 1520 reflectdata.MarkTypeUsedInInterface(t, lsym) 1521} 1522 1523// getDictionarySym returns the dictionary for the named generic function gf, which 1524// is instantiated with the type arguments targs. 1525func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) *types.Sym { 1526 if len(targs) == 0 { 1527 base.Fatalf("%s should have type arguments", gf.Sym().Name) 1528 } 1529 1530 // Enforce that only concrete types can make it to here. 1531 for _, t := range targs { 1532 if t.HasShape() { 1533 panic(fmt.Sprintf("shape %+v in dictionary for %s", t, gf.Sym().Name)) 1534 } 1535 } 1536 1537 // Get a symbol representing the dictionary. 1538 sym := typecheck.MakeDictSym(gf.Sym(), targs, isMeth) 1539 1540 // Initialize the dictionary, if we haven't yet already. 1541 lsym := sym.Linksym() 1542 if len(lsym.P) > 0 { 1543 // We already started creating this dictionary and its lsym. 1544 return sym 1545 } 1546 1547 infoPrint("=== Creating dictionary %v\n", sym.Name) 1548 off := 0 1549 // Emit an entry for each targ (concrete type or gcshape). 1550 for _, t := range targs { 1551 infoPrint(" * %v\n", t) 1552 s := reflectdata.TypeLinksym(t) 1553 off = objw.SymPtr(lsym, off, s, 0) 1554 markTypeUsed(t, lsym) 1555 } 1556 1557 instInfo := g.getInstantiation(gf, targs, isMeth) 1558 info := instInfo.dictInfo 1559 1560 subst := typecheck.Tsubster{ 1561 Tparams: info.shapeParams, 1562 Targs: targs, 1563 } 1564 // Emit an entry for each derived type (after substituting targs) 1565 for _, t := range info.derivedTypes { 1566 ts := subst.Typ(t) 1567 infoPrint(" - %v\n", ts) 1568 s := reflectdata.TypeLinksym(ts) 1569 off = objw.SymPtr(lsym, off, s, 0) 1570 markTypeUsed(ts, lsym) 1571 } 1572 // Emit an entry for each subdictionary (after substituting targs) 1573 for _, n := range info.subDictCalls { 1574 var sym *types.Sym 1575 switch n.Op() { 1576 case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH: 1577 call := n.(*ir.CallExpr) 1578 if call.X.Op() == ir.OXDOT || call.X.Op() == ir.ODOTMETH { 1579 var nameNode *ir.Name 1580 se := call.X.(*ir.SelectorExpr) 1581 if se.X.Type().IsShape() { 1582 // This is a method call enabled by a type bound. 1583 1584 // We need this extra check for method expressions, 1585 // which don't add in the implicit XDOTs. 1586 tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel) 1587 tmpse = typecheck.AddImplicitDots(tmpse) 1588 tparam := tmpse.X.Type() 1589 if !tparam.IsShape() { 1590 // The method expression is not 1591 // really on a typeparam. 1592 break 1593 } 1594 ix := -1 1595 for i, shape := range info.shapeParams { 1596 if shape == tparam { 1597 ix = i 1598 break 1599 } 1600 } 1601 assert(ix >= 0) 1602 recvType := targs[ix] 1603 if recvType.IsInterface() || len(recvType.RParams()) == 0 { 1604 // No sub-dictionary entry is 1605 // actually needed, since the 1606 // type arg is not an 1607 // instantiated type that 1608 // will have generic methods. 1609 break 1610 } 1611 // This is a method call for an 1612 // instantiated type, so we need a 1613 // sub-dictionary. 1614 targs := recvType.RParams() 1615 genRecvType := recvType.OrigSym().Def.Type() 1616 nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) 1617 sym = g.getDictionarySym(nameNode, targs, true) 1618 } else { 1619 // This is the case of a normal 1620 // method call on a generic type. 1621 recvType := deref(call.X.(*ir.SelectorExpr).X.Type()) 1622 genRecvType := recvType.OrigSym().Def.Type() 1623 nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) 1624 subtargs := recvType.RParams() 1625 s2targs := make([]*types.Type, len(subtargs)) 1626 for i, t := range subtargs { 1627 s2targs[i] = subst.Typ(t) 1628 } 1629 sym = g.getDictionarySym(nameNode, s2targs, true) 1630 } 1631 } else { 1632 inst := call.X.(*ir.InstExpr) 1633 var nameNode *ir.Name 1634 var meth *ir.SelectorExpr 1635 var isMeth bool 1636 if meth, isMeth = inst.X.(*ir.SelectorExpr); isMeth { 1637 nameNode = meth.Selection.Nname.(*ir.Name) 1638 } else { 1639 nameNode = inst.X.(*ir.Name) 1640 } 1641 subtargs := typecheck.TypesOf(inst.Targs) 1642 for i, t := range subtargs { 1643 subtargs[i] = subst.Typ(t) 1644 } 1645 sym = g.getDictionarySym(nameNode, subtargs, isMeth) 1646 } 1647 1648 case ir.OFUNCINST: 1649 inst := n.(*ir.InstExpr) 1650 nameNode := inst.X.(*ir.Name) 1651 subtargs := typecheck.TypesOf(inst.Targs) 1652 for i, t := range subtargs { 1653 subtargs[i] = subst.Typ(t) 1654 } 1655 sym = g.getDictionarySym(nameNode, subtargs, false) 1656 1657 case ir.OXDOT, ir.OMETHEXPR, ir.OMETHVALUE: 1658 selExpr := n.(*ir.SelectorExpr) 1659 recvType := deref(selExpr.Selection.Type.Recv().Type) 1660 genRecvType := recvType.OrigSym().Def.Type() 1661 subtargs := recvType.RParams() 1662 s2targs := make([]*types.Type, len(subtargs)) 1663 for i, t := range subtargs { 1664 s2targs[i] = subst.Typ(t) 1665 } 1666 nameNode := typecheck.Lookdot1(selExpr, selExpr.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) 1667 sym = g.getDictionarySym(nameNode, s2targs, true) 1668 1669 default: 1670 assert(false) 1671 } 1672 1673 if sym == nil { 1674 // Unused sub-dictionary entry, just emit 0. 1675 off = objw.Uintptr(lsym, off, 0) 1676 infoPrint(" - Unused subdict entry\n") 1677 } else { 1678 off = objw.SymPtr(lsym, off, sym.Linksym(), 0) 1679 infoPrint(" - Subdict %v\n", sym.Name) 1680 } 1681 } 1682 1683 g.instantiateMethods() 1684 delay := &delayInfo{ 1685 gf: gf, 1686 targs: targs, 1687 sym: sym, 1688 off: off, 1689 isMeth: isMeth, 1690 } 1691 g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay) 1692 return sym 1693} 1694 1695// finalizeSyms finishes up all dictionaries on g.dictSymsToFinalize, by writing out 1696// any needed LSyms for itabs. The itab lsyms create wrappers which need various 1697// dictionaries and method instantiations to be complete, so, to avoid recursive 1698// dependencies, we finalize the itab lsyms only after all dictionaries syms and 1699// instantiations have been created. 1700func (g *genInst) finalizeSyms() { 1701 for _, d := range g.dictSymsToFinalize { 1702 infoPrint("=== Finalizing dictionary %s\n", d.sym.Name) 1703 1704 lsym := d.sym.Linksym() 1705 instInfo := g.getInstantiation(d.gf, d.targs, d.isMeth) 1706 info := instInfo.dictInfo 1707 1708 subst := typecheck.Tsubster{ 1709 Tparams: info.shapeParams, 1710 Targs: d.targs, 1711 } 1712 1713 // Emit an entry for each itab 1714 for _, n := range info.itabConvs { 1715 var srctype, dsttype *types.Type 1716 switch n.Op() { 1717 case ir.OXDOT, ir.OMETHVALUE: 1718 se := n.(*ir.SelectorExpr) 1719 srctype = subst.Typ(se.X.Type()) 1720 dsttype = subst.Typ(info.shapeToBound[se.X.Type()]) 1721 case ir.ODOTTYPE, ir.ODOTTYPE2: 1722 srctype = subst.Typ(n.(*ir.TypeAssertExpr).Type()) 1723 dsttype = subst.Typ(n.(*ir.TypeAssertExpr).X.Type()) 1724 case ir.OCONVIFACE: 1725 srctype = subst.Typ(n.(*ir.ConvExpr).X.Type()) 1726 dsttype = subst.Typ(n.Type()) 1727 case ir.OTYPE: 1728 srctype = subst.Typ(n.Type()) 1729 dsttype = subst.Typ(info.type2switchType[n]) 1730 default: 1731 base.Fatalf("itab entry with unknown op %s", n.Op()) 1732 } 1733 if srctype.IsInterface() || dsttype.IsEmptyInterface() { 1734 // No itab is wanted if src type is an interface. We 1735 // will use a type assert instead. 1736 d.off = objw.Uintptr(lsym, d.off, 0) 1737 infoPrint(" + Unused itab entry for %v\n", srctype) 1738 } else { 1739 // Make sure all new fully-instantiated types have 1740 // their methods created before generating any itabs. 1741 g.instantiateMethods() 1742 itabLsym := reflectdata.ITabLsym(srctype, dsttype) 1743 d.off = objw.SymPtr(lsym, d.off, itabLsym, 0) 1744 infoPrint(" + Itab for (%v,%v)\n", srctype, dsttype) 1745 } 1746 } 1747 1748 objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA) 1749 infoPrint("=== Finalized dictionary %s\n", d.sym.Name) 1750 } 1751 g.dictSymsToFinalize = nil 1752} 1753 1754func (g *genInst) getDictionaryValue(pos src.XPos, gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { 1755 sym := g.getDictionarySym(gf, targs, isMeth) 1756 1757 // Make (or reuse) a node referencing the dictionary symbol. 1758 var n *ir.Name 1759 if sym.Def != nil { 1760 n = sym.Def.(*ir.Name) 1761 } else { 1762 // We set the position of a static dictionary to be the position of 1763 // one of its uses. 1764 n = ir.NewNameAt(pos, sym) 1765 n.Curfn = ir.CurFunc 1766 n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter 1767 n.SetTypecheck(1) 1768 n.Class = ir.PEXTERN 1769 sym.Def = n 1770 } 1771 1772 // Return the address of the dictionary. Addr node gets position that was passed in. 1773 np := typecheck.NodAddrAt(pos, n) 1774 // Note: treat dictionary pointers as uintptrs, so they aren't pointers 1775 // with respect to GC. That saves on stack scanning work, write barriers, etc. 1776 // We can get away with it because dictionaries are global variables. 1777 // TODO: use a cast, or is typing directly ok? 1778 np.SetType(types.Types[types.TUINTPTR]) 1779 np.SetTypecheck(1) 1780 return np 1781} 1782 1783// hasShapeNodes returns true if the type of any node in targs has a shape. 1784func hasShapeNodes(targs []ir.Node) bool { 1785 for _, n := range targs { 1786 if n.Type().HasShape() { 1787 return true 1788 } 1789 } 1790 return false 1791} 1792 1793// hasShapeTypes returns true if any type in targs has a shape. 1794func hasShapeTypes(targs []*types.Type) bool { 1795 for _, t := range targs { 1796 if t.HasShape() { 1797 return true 1798 } 1799 } 1800 return false 1801} 1802 1803// getInstInfo get the dictionary format for a function instantiation- type params, derived 1804// types, and needed subdictionaries and itabs. 1805func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) { 1806 info := instInfo.dictInfo 1807 info.shapeParams = shapes 1808 1809 for _, t := range info.shapeParams { 1810 b := info.shapeToBound[t] 1811 if b.HasShape() { 1812 // If a type bound is parameterized (unusual case), then we 1813 // may need its derived type to do a type assert when doing a 1814 // bound call for a type arg that is an interface. 1815 addType(info, nil, b) 1816 } 1817 } 1818 1819 for _, n := range st.Dcl { 1820 addType(info, n, n.Type()) 1821 n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1) 1822 } 1823 1824 if infoPrintMode { 1825 fmt.Printf(">>> InstInfo for %v\n", st) 1826 for _, t := range info.shapeParams { 1827 fmt.Printf(" Typeparam %v\n", t) 1828 } 1829 } 1830 1831 // Map to remember when we have seen an instantiated function value or method 1832 // expression/value as part of a call, so we can determine when we encounter 1833 // an uncalled function value or method expression/value. 1834 callMap := make(map[ir.Node]bool) 1835 1836 var visitFunc func(ir.Node) 1837 visitFunc = func(n ir.Node) { 1838 switch n.Op() { 1839 case ir.OFUNCINST: 1840 if !callMap[n] && hasShapeNodes(n.(*ir.InstExpr).Targs) { 1841 infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X) 1842 info.subDictCalls = append(info.subDictCalls, n) 1843 } 1844 case ir.OMETHEXPR, ir.OMETHVALUE: 1845 if !callMap[n] && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) && 1846 len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && 1847 hasShapeTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { 1848 if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { 1849 infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) 1850 } else { 1851 infoPrint(" Closure&subdictionary required at generic meth value %v\n", n) 1852 } 1853 info.subDictCalls = append(info.subDictCalls, n) 1854 } 1855 case ir.OCALL: 1856 ce := n.(*ir.CallExpr) 1857 if ce.X.Op() == ir.OFUNCINST { 1858 callMap[ce.X] = true 1859 if hasShapeNodes(ce.X.(*ir.InstExpr).Targs) { 1860 infoPrint(" Subdictionary at generic function/method call: %v - %v\n", ce.X.(*ir.InstExpr).X, n) 1861 info.subDictCalls = append(info.subDictCalls, n) 1862 } 1863 } 1864 if ce.X.Op() == ir.OXDOT && 1865 isShapeDeref(ce.X.(*ir.SelectorExpr).X.Type()) { 1866 callMap[ce.X] = true 1867 infoPrint(" Optional subdictionary at generic bound call: %v\n", n) 1868 info.subDictCalls = append(info.subDictCalls, n) 1869 } 1870 case ir.OCALLMETH: 1871 ce := n.(*ir.CallExpr) 1872 if ce.X.Op() == ir.ODOTMETH && 1873 len(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { 1874 callMap[ce.X] = true 1875 if hasShapeTypes(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) { 1876 infoPrint(" Subdictionary at generic method call: %v\n", n) 1877 info.subDictCalls = append(info.subDictCalls, n) 1878 } 1879 } 1880 case ir.OCONVIFACE: 1881 if n.Type().IsInterface() && !n.Type().IsEmptyInterface() && 1882 n.(*ir.ConvExpr).X.Type().HasShape() { 1883 infoPrint(" Itab for interface conv: %v\n", n) 1884 info.itabConvs = append(info.itabConvs, n) 1885 } 1886 case ir.OXDOT: 1887 if n.(*ir.SelectorExpr).X.Type().IsShape() { 1888 infoPrint(" Itab for bound call: %v\n", n) 1889 info.itabConvs = append(info.itabConvs, n) 1890 } 1891 case ir.ODOTTYPE, ir.ODOTTYPE2: 1892 if !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() { 1893 infoPrint(" Itab for dot type: %v\n", n) 1894 info.itabConvs = append(info.itabConvs, n) 1895 } 1896 case ir.OCLOSURE: 1897 // Visit the closure body and add all relevant entries to the 1898 // dictionary of the outer function (closure will just use 1899 // the dictionary of the outer function). 1900 cfunc := n.(*ir.ClosureExpr).Func 1901 for _, n1 := range cfunc.Body { 1902 ir.Visit(n1, visitFunc) 1903 } 1904 for _, n := range cfunc.Dcl { 1905 n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1) 1906 } 1907 case ir.OSWITCH: 1908 ss := n.(*ir.SwitchStmt) 1909 if ss.Tag != nil && ss.Tag.Op() == ir.OTYPESW && 1910 !ss.Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() { 1911 for _, cc := range ss.Cases { 1912 for _, c := range cc.List { 1913 if c.Op() == ir.OTYPE && c.Type().HasShape() { 1914 // Type switch from a non-empty interface - might need an itab. 1915 infoPrint(" Itab for type switch: %v\n", c) 1916 info.itabConvs = append(info.itabConvs, c) 1917 if info.type2switchType == nil { 1918 info.type2switchType = map[ir.Node]*types.Type{} 1919 } 1920 info.type2switchType[c] = ss.Tag.(*ir.TypeSwitchGuard).X.Type() 1921 } 1922 } 1923 } 1924 } 1925 } 1926 addType(info, n, n.Type()) 1927 } 1928 1929 for _, stmt := range st.Body { 1930 ir.Visit(stmt, visitFunc) 1931 } 1932 if infoPrintMode { 1933 for _, t := range info.derivedTypes { 1934 fmt.Printf(" Derived type %v\n", t) 1935 } 1936 fmt.Printf(">>> Done Instinfo\n") 1937 } 1938 info.startSubDict = len(info.shapeParams) + len(info.derivedTypes) 1939 info.startItabConv = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) 1940 info.dictLen = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs) 1941} 1942 1943// isShapeDeref returns true if t is either a shape or a pointer to a shape. (We 1944// can't just use deref(t).IsShape(), since a shape type is a complex type and may 1945// have a pointer as part of its shape.) 1946func isShapeDeref(t *types.Type) bool { 1947 return t.IsShape() || t.IsPtr() && t.Elem().IsShape() 1948} 1949 1950// addType adds t to info.derivedTypes if it is parameterized type (which is not 1951// just a simple shape) that is different from any existing type on 1952// info.derivedTypes. 1953func addType(info *dictInfo, n ir.Node, t *types.Type) { 1954 if t == nil || !t.HasShape() { 1955 return 1956 } 1957 if t.IsShape() { 1958 return 1959 } 1960 if t.Kind() == types.TFUNC && n != nil && 1961 (t.Recv() != nil || n.Op() == ir.ONAME && n.Name().Class == ir.PFUNC) { 1962 // Don't use the type of a named generic function or method, 1963 // since that is parameterized by other typeparams. 1964 // (They all come from arguments of a FUNCINST node.) 1965 return 1966 } 1967 if doubleCheck && !parameterizedBy(t, info.shapeParams) { 1968 base.Fatalf("adding type with invalid parameters %+v", t) 1969 } 1970 if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() { 1971 // Multiple return values are not a relevant new type (?). 1972 return 1973 } 1974 // Ignore a derived type we've already added. 1975 for _, et := range info.derivedTypes { 1976 if types.IdenticalStrict(t, et) { 1977 return 1978 } 1979 } 1980 info.derivedTypes = append(info.derivedTypes, t) 1981} 1982 1983// parameterizedBy returns true if t is parameterized by (at most) params. 1984func parameterizedBy(t *types.Type, params []*types.Type) bool { 1985 return parameterizedBy1(t, params, map[*types.Type]bool{}) 1986} 1987func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Type]bool) bool { 1988 if visited[t] { 1989 return true 1990 } 1991 visited[t] = true 1992 1993 if t.Sym() != nil && len(t.RParams()) > 0 { 1994 // This defined type is instantiated. Check the instantiating types. 1995 for _, r := range t.RParams() { 1996 if !parameterizedBy1(r, params, visited) { 1997 return false 1998 } 1999 } 2000 return true 2001 } 2002 if t.IsShape() { 2003 // Check if t is one of the allowed parameters in scope. 2004 for _, p := range params { 2005 if p == t { 2006 return true 2007 } 2008 } 2009 // Couldn't find t in the list of allowed parameters. 2010 return false 2011 2012 } 2013 switch t.Kind() { 2014 case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN: 2015 return parameterizedBy1(t.Elem(), params, visited) 2016 2017 case types.TMAP: 2018 return parameterizedBy1(t.Key(), params, visited) && parameterizedBy1(t.Elem(), params, visited) 2019 2020 case types.TFUNC: 2021 return parameterizedBy1(t.TParams(), params, visited) && parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited) 2022 2023 case types.TSTRUCT: 2024 for _, f := range t.Fields().Slice() { 2025 if !parameterizedBy1(f.Type, params, visited) { 2026 return false 2027 } 2028 } 2029 return true 2030 2031 case types.TINTER: 2032 for _, f := range t.Methods().Slice() { 2033 if !parameterizedBy1(f.Type, params, visited) { 2034 return false 2035 } 2036 } 2037 return true 2038 2039 case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64, 2040 types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, 2041 types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR: 2042 return true 2043 2044 case types.TUNION: 2045 for i := 0; i < t.NumTerms(); i++ { 2046 tt, _ := t.Term(i) 2047 if !parameterizedBy1(tt, params, visited) { 2048 return false 2049 } 2050 } 2051 return true 2052 2053 default: 2054 base.Fatalf("bad type kind %+v", t) 2055 return true 2056 } 2057} 2058 2059// startClosures starts creation of a closure that has the function type typ. It 2060// creates all the formal params and results according to the type typ. On return, 2061// the body and closure variables of the closure must still be filled in, and 2062// ir.UseClosure() called. 2063func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*types.Field, []*types.Field) { 2064 // Make a new internal function. 2065 fn := ir.NewClosureFunc(pos, outer != nil) 2066 ir.NameClosure(fn.OClosure, outer) 2067 2068 // Build formal argument and return lists. 2069 var formalParams []*types.Field // arguments of closure 2070 var formalResults []*types.Field // returns of closure 2071 for i := 0; i < typ.NumParams(); i++ { 2072 t := typ.Params().Field(i).Type 2073 arg := ir.NewNameAt(pos, typecheck.LookupNum("a", i)) 2074 arg.Class = ir.PPARAM 2075 typed(t, arg) 2076 arg.Curfn = fn 2077 fn.Dcl = append(fn.Dcl, arg) 2078 f := types.NewField(pos, arg.Sym(), t) 2079 f.Nname = arg 2080 f.SetIsDDD(typ.Params().Field(i).IsDDD()) 2081 formalParams = append(formalParams, f) 2082 } 2083 for i := 0; i < typ.NumResults(); i++ { 2084 t := typ.Results().Field(i).Type 2085 result := ir.NewNameAt(pos, typecheck.LookupNum("r", i)) // TODO: names not needed? 2086 result.Class = ir.PPARAMOUT 2087 typed(t, result) 2088 result.Curfn = fn 2089 fn.Dcl = append(fn.Dcl, result) 2090 f := types.NewField(pos, result.Sym(), t) 2091 f.Nname = result 2092 formalResults = append(formalResults, f) 2093 } 2094 2095 // Build an internal function with the right signature. 2096 closureType := types.NewSignature(typ.Pkg(), nil, nil, formalParams, formalResults) 2097 typed(closureType, fn.Nname) 2098 typed(typ, fn.OClosure) 2099 fn.SetTypecheck(1) 2100 return fn, formalParams, formalResults 2101 2102} 2103 2104// assertToBound returns a new node that converts a node rcvr with interface type to 2105// the 'dst' interface type. 2106func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, dst *types.Type) ir.Node { 2107 if dst.HasShape() { 2108 ix := findDictType(info, dst) 2109 assert(ix >= 0) 2110 rt := getDictionaryType(info, dictVar, pos, ix) 2111 rcvr = ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, rcvr, rt) 2112 typed(dst, rcvr) 2113 } else { 2114 rcvr = ir.NewTypeAssertExpr(pos, rcvr, nil) 2115 typed(dst, rcvr) 2116 } 2117 return rcvr 2118} 2119 2120// buildClosure2 makes a closure to implement a method expression m (generic form x) 2121// which has a shape type as receiver. If the receiver is exactly a shape (i.e. from 2122// a typeparam), then the body of the closure converts m.X (the receiver) to the 2123// interface bound type, and makes an interface call with the remaining arguments. 2124// 2125// The returned closure is fully substituted and has already had any needed 2126// transformations done. 2127func (g *genInst) buildClosure2(info *instInfo, m ir.Node) ir.Node { 2128 outer := info.fun 2129 pos := m.Pos() 2130 typ := m.Type() // type of the closure 2131 2132 fn, formalParams, formalResults := startClosure(pos, outer, typ) 2133 2134 // Capture dictionary calculated in the outer function 2135 dictVar := ir.CaptureName(pos, fn, info.dictParam) 2136 typed(types.Types[types.TUINTPTR], dictVar) 2137 2138 // Build arguments to call inside the closure. 2139 var args []ir.Node 2140 for i := 0; i < typ.NumParams(); i++ { 2141 args = append(args, formalParams[i].Nname.(*ir.Name)) 2142 } 2143 2144 // Build call itself. This involves converting the first argument to the 2145 // bound type (an interface) using the dictionary, and then making an 2146 // interface call with the remaining arguments. 2147 var innerCall ir.Node 2148 rcvr := args[0] 2149 args = args[1:] 2150 assert(m.(*ir.SelectorExpr).X.Type().IsShape()) 2151 dst := info.dictInfo.shapeToBound[m.(*ir.SelectorExpr).X.Type()] 2152 if m.(*ir.SelectorExpr).X.Type().IsInterface() { 2153 // If type arg is an interface (unusual case), we do a type assert to 2154 // the type bound. 2155 rcvr = assertToBound(info, dictVar, pos, rcvr, dst) 2156 } else { 2157 rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, m, dst) 2158 } 2159 dot := ir.NewSelectorExpr(pos, ir.ODOTINTER, rcvr, m.(*ir.SelectorExpr).Sel) 2160 dot.Selection = typecheck.Lookdot1(dot, dot.Sel, dot.X.Type(), dot.X.Type().AllMethods(), 1) 2161 2162 typed(dot.Selection.Type, dot) 2163 innerCall = ir.NewCallExpr(pos, ir.OCALLINTER, dot, args) 2164 t := m.Type() 2165 if t.NumResults() == 0 { 2166 innerCall.SetTypecheck(1) 2167 } else if t.NumResults() == 1 { 2168 typed(t.Results().Field(0).Type, innerCall) 2169 } else { 2170 typed(t.Results(), innerCall) 2171 } 2172 if len(formalResults) > 0 { 2173 innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall}) 2174 innerCall.SetTypecheck(1) 2175 } 2176 fn.Body = []ir.Node{innerCall} 2177 2178 // We're all done with the captured dictionary 2179 ir.FinishCaptureNames(pos, outer, fn) 2180 2181 // Do final checks on closure and return it. 2182 return ir.UseClosure(fn.OClosure, typecheck.Target) 2183} 2184