github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/cmd/compile/internal/gc/closure.go (about) 1 // Copyright 2009 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 package gc 6 7 import ( 8 "fmt" 9 ) 10 11 // function literals aka closures 12 func closurehdr(ntype *Node) { 13 var name *Node 14 var a *Node 15 16 n := Nod(OCLOSURE, nil, nil) 17 n.Func.Ntype = ntype 18 n.Func.Depth = Funcdepth 19 n.Func.Outerfunc = Curfn 20 21 funchdr(n) 22 23 // steal ntype's argument names and 24 // leave a fresh copy in their place. 25 // references to these variables need to 26 // refer to the variables in the external 27 // function declared below; see walkclosure. 28 n.List.Set(ntype.List.Slice()) 29 30 n.Rlist.Set(ntype.Rlist.Slice()) 31 ntype.List.Set(nil) 32 ntype.Rlist.Set(nil) 33 for _, n1 := range n.List.Slice() { 34 name = n1.Left 35 if name != nil { 36 name = newname(name.Sym) 37 } 38 a = Nod(ODCLFIELD, name, n1.Right) 39 a.Isddd = n1.Isddd 40 if name != nil { 41 name.Isddd = a.Isddd 42 } 43 ntype.List.Append(a) 44 } 45 for _, n2 := range n.Rlist.Slice() { 46 name = n2.Left 47 if name != nil { 48 name = newname(name.Sym) 49 } 50 ntype.Rlist.Append(Nod(ODCLFIELD, name, n2.Right)) 51 } 52 } 53 54 func closurebody(body []*Node) *Node { 55 if len(body) == 0 { 56 body = []*Node{Nod(OEMPTY, nil, nil)} 57 } 58 59 func_ := Curfn 60 func_.Nbody.Set(body) 61 func_.Func.Endlineno = lineno 62 funcbody(func_) 63 64 // closure-specific variables are hanging off the 65 // ordinary ones in the symbol table; see oldname. 66 // unhook them. 67 // make the list of pointers for the closure call. 68 for _, v := range func_.Func.Cvars.Slice() { 69 // Unlink from v1; see comment in syntax.go type Param for these fields. 70 v1 := v.Name.Defn 71 v1.Name.Param.Innermost = v.Name.Param.Outer 72 73 // If the closure usage of v is not dense, 74 // we need to make it dense; now that we're out 75 // of the function in which v appeared, 76 // look up v.Sym in the enclosing function 77 // and keep it around for use in the compiled code. 78 // 79 // That is, suppose we just finished parsing the innermost 80 // closure f4 in this code: 81 // 82 // func f() { 83 // v := 1 84 // func() { // f2 85 // use(v) 86 // func() { // f3 87 // func() { // f4 88 // use(v) 89 // }() 90 // }() 91 // }() 92 // } 93 // 94 // At this point v.Outer is f2's v; there is no f3's v. 95 // To construct the closure f4 from within f3, 96 // we need to use f3's v and in this case we need to create f3's v. 97 // We are now in the context of f3, so calling oldname(v.Sym) 98 // obtains f3's v, creating it if necessary (as it is in the example). 99 // 100 // capturevars will decide whether to use v directly or &v. 101 v.Name.Param.Outer = oldname(v.Sym) 102 } 103 104 return func_ 105 } 106 107 func typecheckclosure(func_ *Node, top int) { 108 for _, ln := range func_.Func.Cvars.Slice() { 109 n := ln.Name.Defn 110 if !n.Name.Captured { 111 n.Name.Captured = true 112 if n.Name.Decldepth == 0 { 113 Fatalf("typecheckclosure: var %v does not have decldepth assigned", Nconv(n, FmtShort)) 114 } 115 116 // Ignore assignments to the variable in straightline code 117 // preceding the first capturing by a closure. 118 if n.Name.Decldepth == decldepth { 119 n.Assigned = false 120 } 121 } 122 } 123 124 for _, ln := range func_.Func.Dcl { 125 if ln.Op == ONAME && (ln.Class == PPARAM || ln.Class == PPARAMOUT) { 126 ln.Name.Decldepth = 1 127 } 128 } 129 130 oldfn := Curfn 131 func_.Func.Ntype = typecheck(func_.Func.Ntype, Etype) 132 func_.Type = func_.Func.Ntype.Type 133 func_.Func.Top = top 134 135 // Type check the body now, but only if we're inside a function. 136 // At top level (in a variable initialization: curfn==nil) we're not 137 // ready to type check code yet; we'll check it later, because the 138 // underlying closure function we create is added to xtop. 139 if Curfn != nil && func_.Type != nil { 140 Curfn = func_ 141 olddd := decldepth 142 decldepth = 1 143 typecheckslice(func_.Nbody.Slice(), Etop) 144 decldepth = olddd 145 Curfn = oldfn 146 } 147 148 // Create top-level function 149 xtop = append(xtop, makeclosure(func_)) 150 } 151 152 // closurename returns name for OCLOSURE n. 153 // It is not as simple as it ought to be, because we typecheck nested closures 154 // starting from the innermost one. So when we check the inner closure, 155 // we don't yet have name for the outer closure. This function uses recursion 156 // to generate names all the way up if necessary. 157 158 var closurename_closgen int 159 160 func closurename(n *Node) *Sym { 161 if n.Sym != nil { 162 return n.Sym 163 } 164 gen := 0 165 outer := "" 166 prefix := "" 167 if n.Func.Outerfunc == nil { 168 // Global closure. 169 outer = "glob" 170 171 prefix = "func" 172 closurename_closgen++ 173 gen = closurename_closgen 174 } else if n.Func.Outerfunc.Op == ODCLFUNC { 175 // The outermost closure inside of a named function. 176 outer = n.Func.Outerfunc.Func.Nname.Sym.Name 177 178 prefix = "func" 179 180 // Yes, functions can be named _. 181 // Can't use function closgen in such case, 182 // because it would lead to name clashes. 183 if !isblank(n.Func.Outerfunc.Func.Nname) { 184 n.Func.Outerfunc.Func.Closgen++ 185 gen = n.Func.Outerfunc.Func.Closgen 186 } else { 187 closurename_closgen++ 188 gen = closurename_closgen 189 } 190 } else if n.Func.Outerfunc.Op == OCLOSURE { 191 // Nested closure, recurse. 192 outer = closurename(n.Func.Outerfunc).Name 193 194 prefix = "" 195 n.Func.Outerfunc.Func.Closgen++ 196 gen = n.Func.Outerfunc.Func.Closgen 197 } else { 198 Fatalf("closurename called for %v", Nconv(n, FmtShort)) 199 } 200 n.Sym = Lookupf("%s.%s%d", outer, prefix, gen) 201 return n.Sym 202 } 203 204 func makeclosure(func_ *Node) *Node { 205 // wrap body in external function 206 // that begins by reading closure parameters. 207 xtype := Nod(OTFUNC, nil, nil) 208 209 xtype.List.Set(func_.List.Slice()) 210 xtype.Rlist.Set(func_.Rlist.Slice()) 211 212 // create the function 213 xfunc := Nod(ODCLFUNC, nil, nil) 214 215 xfunc.Func.Nname = newfuncname(closurename(func_)) 216 xfunc.Func.Nname.Sym.Flags |= SymExported // disable export 217 xfunc.Func.Nname.Name.Param.Ntype = xtype 218 xfunc.Func.Nname.Name.Defn = xfunc 219 declare(xfunc.Func.Nname, PFUNC) 220 xfunc.Func.Nname.Name.Funcdepth = func_.Func.Depth 221 xfunc.Func.Depth = func_.Func.Depth 222 xfunc.Func.Endlineno = func_.Func.Endlineno 223 makefuncsym(xfunc.Func.Nname.Sym) 224 225 xfunc.Nbody.Set(func_.Nbody.Slice()) 226 xfunc.Func.Dcl = append(func_.Func.Dcl, xfunc.Func.Dcl...) 227 func_.Func.Dcl = nil 228 if xfunc.Nbody.Len() == 0 { 229 Fatalf("empty body - won't generate any code") 230 } 231 xfunc = typecheck(xfunc, Etop) 232 233 xfunc.Func.Closure = func_ 234 func_.Func.Closure = xfunc 235 236 func_.Nbody.Set(nil) 237 func_.List.Set(nil) 238 func_.Rlist.Set(nil) 239 240 return xfunc 241 } 242 243 // capturevars is called in a separate phase after all typechecking is done. 244 // It decides whether each variable captured by a closure should be captured 245 // by value or by reference. 246 // We use value capturing for values <= 128 bytes that are never reassigned 247 // after capturing (effectively constant). 248 func capturevars(xfunc *Node) { 249 lno := lineno 250 lineno = xfunc.Lineno 251 252 func_ := xfunc.Func.Closure 253 func_.Func.Enter.Set(nil) 254 for _, v := range func_.Func.Cvars.Slice() { 255 if v.Type == nil { 256 // if v->type is nil, it means v looked like it was 257 // going to be used in the closure but wasn't. 258 // this happens because when parsing a, b, c := f() 259 // the a, b, c gets parsed as references to older 260 // a, b, c before the parser figures out this is a 261 // declaration. 262 v.Op = OXXX 263 264 continue 265 } 266 267 // type check the & of closed variables outside the closure, 268 // so that the outer frame also grabs them and knows they escape. 269 dowidth(v.Type) 270 271 outer := v.Name.Param.Outer 272 outermost := v.Name.Defn 273 274 // out parameters will be assigned to implicitly upon return. 275 if outer.Class != PPARAMOUT && !outermost.Addrtaken && !outermost.Assigned && v.Type.Width <= 128 { 276 v.Name.Byval = true 277 } else { 278 outermost.Addrtaken = true 279 outer = Nod(OADDR, outer, nil) 280 } 281 282 if Debug['m'] > 1 { 283 var name *Sym 284 if v.Name.Curfn != nil && v.Name.Curfn.Func.Nname != nil { 285 name = v.Name.Curfn.Func.Nname.Sym 286 } 287 how := "ref" 288 if v.Name.Byval { 289 how = "value" 290 } 291 Warnl(v.Lineno, "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, outermost.Addrtaken, outermost.Assigned, int32(v.Type.Width)) 292 } 293 294 outer = typecheck(outer, Erv) 295 func_.Func.Enter.Append(outer) 296 } 297 298 lineno = lno 299 } 300 301 // transformclosure is called in a separate phase after escape analysis. 302 // It transform closure bodies to properly reference captured variables. 303 func transformclosure(xfunc *Node) { 304 lno := lineno 305 lineno = xfunc.Lineno 306 func_ := xfunc.Func.Closure 307 308 if func_.Func.Top&Ecall != 0 { 309 // If the closure is directly called, we transform it to a plain function call 310 // with variables passed as args. This avoids allocation of a closure object. 311 // Here we do only a part of the transformation. Walk of OCALLFUNC(OCLOSURE) 312 // will complete the transformation later. 313 // For illustration, the following closure: 314 // func(a int) { 315 // println(byval) 316 // byref++ 317 // }(42) 318 // becomes: 319 // func(a int, byval int, &byref *int) { 320 // println(byval) 321 // (*&byref)++ 322 // }(byval, &byref, 42) 323 324 // f is ONAME of the actual function. 325 f := xfunc.Func.Nname 326 327 // We are going to insert captured variables before input args. 328 var params []*Field 329 var decls []*Node 330 for _, v := range func_.Func.Cvars.Slice() { 331 if v.Op == OXXX { 332 continue 333 } 334 fld := newField() 335 fld.Funarg = FunargParams 336 if v.Name.Byval { 337 // If v is captured by value, we merely downgrade it to PPARAM. 338 v.Class = PPARAM 339 340 v.Ullman = 1 341 fld.Nname = v 342 } else { 343 // If v of type T is captured by reference, 344 // we introduce function param &v *T 345 // and v remains PAUTOHEAP with &v heapaddr 346 // (accesses will implicitly deref &v). 347 addr := newname(Lookupf("&%s", v.Sym.Name)) 348 addr.Type = Ptrto(v.Type) 349 addr.Class = PPARAM 350 v.Name.Heapaddr = addr 351 fld.Nname = addr 352 } 353 354 fld.Type = fld.Nname.Type 355 fld.Sym = fld.Nname.Sym 356 357 params = append(params, fld) 358 decls = append(decls, fld.Nname) 359 } 360 361 if len(params) > 0 { 362 // Prepend params and decls. 363 f.Type.Params().SetFields(append(params, f.Type.Params().FieldSlice()...)) 364 xfunc.Func.Dcl = append(decls, xfunc.Func.Dcl...) 365 } 366 367 // Recalculate param offsets. 368 if f.Type.Width > 0 { 369 Fatalf("transformclosure: width is already calculated") 370 } 371 dowidth(f.Type) 372 xfunc.Type = f.Type // update type of ODCLFUNC 373 } else { 374 // The closure is not called, so it is going to stay as closure. 375 var body []*Node 376 offset := int64(Widthptr) 377 var addr *Node 378 var cv *Node 379 for _, v := range func_.Func.Cvars.Slice() { 380 if v.Op == OXXX { 381 continue 382 } 383 384 // cv refers to the field inside of closure OSTRUCTLIT. 385 cv = Nod(OCLOSUREVAR, nil, nil) 386 387 cv.Type = v.Type 388 if !v.Name.Byval { 389 cv.Type = Ptrto(v.Type) 390 } 391 offset = Rnd(offset, int64(cv.Type.Align)) 392 cv.Xoffset = offset 393 offset += cv.Type.Width 394 395 if v.Name.Byval && v.Type.Width <= int64(2*Widthptr) { 396 // If it is a small variable captured by value, downgrade it to PAUTO. 397 v.Class = PAUTO 398 v.Ullman = 1 399 xfunc.Func.Dcl = append(xfunc.Func.Dcl, v) 400 body = append(body, Nod(OAS, v, cv)) 401 } else { 402 // Declare variable holding addresses taken from closure 403 // and initialize in entry prologue. 404 addr = newname(Lookupf("&%s", v.Sym.Name)) 405 addr.Name.Param.Ntype = Nod(OIND, typenod(v.Type), nil) 406 addr.Class = PAUTO 407 addr.Used = true 408 addr.Name.Curfn = xfunc 409 xfunc.Func.Dcl = append(xfunc.Func.Dcl, addr) 410 v.Name.Heapaddr = addr 411 if v.Name.Byval { 412 cv = Nod(OADDR, cv, nil) 413 } 414 body = append(body, Nod(OAS, addr, cv)) 415 } 416 } 417 418 if len(body) > 0 { 419 typecheckslice(body, Etop) 420 walkstmtlist(body) 421 xfunc.Func.Enter.Set(body) 422 xfunc.Func.Needctxt = true 423 } 424 } 425 426 lineno = lno 427 } 428 429 // hasemptycvars returns true iff closure func_ has an 430 // empty list of captured vars. OXXX nodes don't count. 431 func hasemptycvars(func_ *Node) bool { 432 for _, v := range func_.Func.Cvars.Slice() { 433 if v.Op == OXXX { 434 continue 435 } 436 return false 437 } 438 return true 439 } 440 441 // closuredebugruntimecheck applies boilerplate checks for debug flags 442 // and compiling runtime 443 func closuredebugruntimecheck(r *Node) { 444 if Debug_closure > 0 { 445 if r.Esc == EscHeap { 446 Warnl(r.Lineno, "heap closure, captured vars = %v", r.Func.Cvars) 447 } else { 448 Warnl(r.Lineno, "stack closure, captured vars = %v", r.Func.Cvars) 449 } 450 } 451 if compiling_runtime && r.Esc == EscHeap { 452 yyerrorl(r.Lineno, "heap-allocated closure, not allowed in runtime.") 453 } 454 } 455 456 func walkclosure(func_ *Node, init *Nodes) *Node { 457 // If no closure vars, don't bother wrapping. 458 if hasemptycvars(func_) { 459 if Debug_closure > 0 { 460 Warnl(func_.Lineno, "closure converted to global") 461 } 462 return func_.Func.Closure.Func.Nname 463 } else { 464 closuredebugruntimecheck(func_) 465 } 466 467 // Create closure in the form of a composite literal. 468 // supposing the closure captures an int i and a string s 469 // and has one float64 argument and no results, 470 // the generated code looks like: 471 // 472 // clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s} 473 // 474 // The use of the struct provides type information to the garbage 475 // collector so that it can walk the closure. We could use (in this case) 476 // [3]unsafe.Pointer instead, but that would leave the gc in the dark. 477 // The information appears in the binary in the form of type descriptors; 478 // the struct is unnamed so that closures in multiple packages with the 479 // same struct type can share the descriptor. 480 481 typ := Nod(OTSTRUCT, nil, nil) 482 483 typ.List.Set1(Nod(ODCLFIELD, newname(Lookup(".F")), typenod(Types[TUINTPTR]))) 484 var typ1 *Node 485 for _, v := range func_.Func.Cvars.Slice() { 486 if v.Op == OXXX { 487 continue 488 } 489 typ1 = typenod(v.Type) 490 if !v.Name.Byval { 491 typ1 = Nod(OIND, typ1, nil) 492 } 493 typ.List.Append(Nod(ODCLFIELD, newname(v.Sym), typ1)) 494 } 495 496 clos := Nod(OCOMPLIT, nil, Nod(OIND, typ, nil)) 497 clos.Esc = func_.Esc 498 clos.Right.Implicit = true 499 clos.List.Set(append([]*Node{Nod(OCFUNC, func_.Func.Closure.Func.Nname, nil)}, func_.Func.Enter.Slice()...)) 500 501 // Force type conversion from *struct to the func type. 502 clos = Nod(OCONVNOP, clos, nil) 503 504 clos.Type = func_.Type 505 506 clos = typecheck(clos, Erv) 507 508 // typecheck will insert a PTRLIT node under CONVNOP, 509 // tag it with escape analysis result. 510 clos.Left.Esc = func_.Esc 511 512 // non-escaping temp to use, if any. 513 // orderexpr did not compute the type; fill it in now. 514 if x := prealloc[func_]; x != nil { 515 x.Type = clos.Left.Left.Type 516 x.Orig.Type = x.Type 517 clos.Left.Right = x 518 delete(prealloc, func_) 519 } 520 521 return walkexpr(clos, init) 522 } 523 524 func typecheckpartialcall(fn *Node, sym *Sym) { 525 switch fn.Op { 526 case ODOTINTER, ODOTMETH: 527 break 528 529 default: 530 Fatalf("invalid typecheckpartialcall") 531 } 532 533 // Create top-level function. 534 xfunc := makepartialcall(fn, fn.Type, sym) 535 fn.Func = xfunc.Func 536 fn.Right = newname(sym) 537 fn.Op = OCALLPART 538 fn.Type = xfunc.Type 539 } 540 541 var makepartialcall_gopkg *Pkg 542 543 func makepartialcall(fn *Node, t0 *Type, meth *Sym) *Node { 544 var p string 545 546 rcvrtype := fn.Left.Type 547 if exportname(meth.Name) { 548 p = fmt.Sprintf("(%v).%s-fm", Tconv(rcvrtype, FmtLeft|FmtShort), meth.Name) 549 } else { 550 p = fmt.Sprintf("(%v).(%v)-fm", Tconv(rcvrtype, FmtLeft|FmtShort), sconv(meth, FmtLeft)) 551 } 552 basetype := rcvrtype 553 if rcvrtype.IsPtr() { 554 basetype = basetype.Elem() 555 } 556 if !basetype.IsInterface() && basetype.Sym == nil { 557 Fatalf("missing base type for %v", rcvrtype) 558 } 559 560 var spkg *Pkg 561 if basetype.Sym != nil { 562 spkg = basetype.Sym.Pkg 563 } 564 if spkg == nil { 565 if makepartialcall_gopkg == nil { 566 makepartialcall_gopkg = mkpkg("go") 567 } 568 spkg = makepartialcall_gopkg 569 } 570 571 sym := Pkglookup(p, spkg) 572 573 if sym.Flags&SymUniq != 0 { 574 return sym.Def 575 } 576 sym.Flags |= SymUniq 577 578 savecurfn := Curfn 579 Curfn = nil 580 581 xtype := Nod(OTFUNC, nil, nil) 582 i := 0 583 var l []*Node 584 var callargs []*Node 585 ddd := false 586 xfunc := Nod(ODCLFUNC, nil, nil) 587 Curfn = xfunc 588 var fld *Node 589 var n *Node 590 for _, t := range t0.Params().Fields().Slice() { 591 n = newname(LookupN("a", i)) 592 i++ 593 n.Class = PPARAM 594 xfunc.Func.Dcl = append(xfunc.Func.Dcl, n) 595 callargs = append(callargs, n) 596 fld = Nod(ODCLFIELD, n, typenod(t.Type)) 597 if t.Isddd { 598 fld.Isddd = true 599 ddd = true 600 } 601 602 l = append(l, fld) 603 } 604 605 xtype.List.Set(l) 606 i = 0 607 l = nil 608 var retargs []*Node 609 for _, t := range t0.Results().Fields().Slice() { 610 n = newname(LookupN("r", i)) 611 i++ 612 n.Class = PPARAMOUT 613 xfunc.Func.Dcl = append(xfunc.Func.Dcl, n) 614 retargs = append(retargs, n) 615 l = append(l, Nod(ODCLFIELD, n, typenod(t.Type))) 616 } 617 618 xtype.Rlist.Set(l) 619 620 xfunc.Func.Dupok = true 621 xfunc.Func.Nname = newfuncname(sym) 622 xfunc.Func.Nname.Sym.Flags |= SymExported // disable export 623 xfunc.Func.Nname.Name.Param.Ntype = xtype 624 xfunc.Func.Nname.Name.Defn = xfunc 625 declare(xfunc.Func.Nname, PFUNC) 626 627 // Declare and initialize variable holding receiver. 628 629 xfunc.Func.Needctxt = true 630 cv := Nod(OCLOSUREVAR, nil, nil) 631 cv.Xoffset = int64(Widthptr) 632 cv.Type = rcvrtype 633 if int(cv.Type.Align) > Widthptr { 634 cv.Xoffset = int64(cv.Type.Align) 635 } 636 ptr := Nod(ONAME, nil, nil) 637 ptr.Sym = Lookup("rcvr") 638 ptr.Class = PAUTO 639 ptr.Addable = true 640 ptr.Ullman = 1 641 ptr.Used = true 642 ptr.Name.Curfn = xfunc 643 ptr.Xoffset = 0 644 xfunc.Func.Dcl = append(xfunc.Func.Dcl, ptr) 645 var body []*Node 646 if rcvrtype.IsPtr() || rcvrtype.IsInterface() { 647 ptr.Name.Param.Ntype = typenod(rcvrtype) 648 body = append(body, Nod(OAS, ptr, cv)) 649 } else { 650 ptr.Name.Param.Ntype = typenod(Ptrto(rcvrtype)) 651 body = append(body, Nod(OAS, ptr, Nod(OADDR, cv, nil))) 652 } 653 654 call := Nod(OCALL, NodSym(OXDOT, ptr, meth), nil) 655 call.List.Set(callargs) 656 call.Isddd = ddd 657 if t0.Results().NumFields() == 0 { 658 body = append(body, call) 659 } else { 660 n := Nod(OAS2, nil, nil) 661 n.List.Set(retargs) 662 n.Rlist.Set1(call) 663 body = append(body, n) 664 n = Nod(ORETURN, nil, nil) 665 body = append(body, n) 666 } 667 668 xfunc.Nbody.Set(body) 669 670 xfunc = typecheck(xfunc, Etop) 671 sym.Def = xfunc 672 xtop = append(xtop, xfunc) 673 Curfn = savecurfn 674 675 return xfunc 676 } 677 678 func walkpartialcall(n *Node, init *Nodes) *Node { 679 // Create closure in the form of a composite literal. 680 // For x.M with receiver (x) type T, the generated code looks like: 681 // 682 // clos = &struct{F uintptr; R T}{M.T·f, x} 683 // 684 // Like walkclosure above. 685 686 if n.Left.Type.IsInterface() { 687 // Trigger panic for method on nil interface now. 688 // Otherwise it happens in the wrapper and is confusing. 689 n.Left = cheapexpr(n.Left, init) 690 691 checknil(n.Left, init) 692 } 693 694 typ := Nod(OTSTRUCT, nil, nil) 695 typ.List.Set1(Nod(ODCLFIELD, newname(Lookup("F")), typenod(Types[TUINTPTR]))) 696 typ.List.Append(Nod(ODCLFIELD, newname(Lookup("R")), typenod(n.Left.Type))) 697 698 clos := Nod(OCOMPLIT, nil, Nod(OIND, typ, nil)) 699 clos.Esc = n.Esc 700 clos.Right.Implicit = true 701 clos.List.Set1(Nod(OCFUNC, n.Func.Nname, nil)) 702 clos.List.Append(n.Left) 703 704 // Force type conversion from *struct to the func type. 705 clos = Nod(OCONVNOP, clos, nil) 706 707 clos.Type = n.Type 708 709 clos = typecheck(clos, Erv) 710 711 // typecheck will insert a PTRLIT node under CONVNOP, 712 // tag it with escape analysis result. 713 clos.Left.Esc = n.Esc 714 715 // non-escaping temp to use, if any. 716 // orderexpr did not compute the type; fill it in now. 717 if x := prealloc[n]; x != nil { 718 x.Type = clos.Left.Left.Type 719 x.Orig.Type = x.Type 720 clos.Left.Right = x 721 delete(prealloc, n) 722 } 723 724 return walkexpr(clos, init) 725 }