github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/compile/internal/gc/walk.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 "cmd/internal/obj" 9 "cmd/internal/sys" 10 "fmt" 11 "strings" 12 ) 13 14 // The constant is known to runtime. 15 const ( 16 tmpstringbufsize = 32 17 ) 18 19 func walk(fn *Node) { 20 Curfn = fn 21 22 if Debug['W'] != 0 { 23 s := fmt.Sprintf("\nbefore %v", Curfn.Func.Nname.Sym) 24 dumplist(s, Curfn.Nbody) 25 } 26 27 lno := lineno 28 29 // Final typecheck for any unused variables. 30 for i, ln := range fn.Func.Dcl { 31 if ln.Op == ONAME && (ln.Class == PAUTO || ln.Class == PAUTOHEAP) { 32 ln = typecheck(ln, Erv|Easgn) 33 fn.Func.Dcl[i] = ln 34 } 35 } 36 37 // Propagate the used flag for typeswitch variables up to the NONAME in it's definition. 38 for _, ln := range fn.Func.Dcl { 39 if ln.Op == ONAME && (ln.Class == PAUTO || ln.Class == PAUTOHEAP) && ln.Name.Defn != nil && ln.Name.Defn.Op == OTYPESW && ln.Used { 40 ln.Name.Defn.Left.Used = true 41 } 42 } 43 44 for _, ln := range fn.Func.Dcl { 45 if ln.Op != ONAME || (ln.Class != PAUTO && ln.Class != PAUTOHEAP) || ln.Sym.Name[0] == '&' || ln.Used { 46 continue 47 } 48 if defn := ln.Name.Defn; defn != nil && defn.Op == OTYPESW { 49 if defn.Left.Used { 50 continue 51 } 52 lineno = defn.Left.Pos 53 yyerror("%v declared and not used", ln.Sym) 54 defn.Left.Used = true // suppress repeats 55 } else { 56 lineno = ln.Pos 57 yyerror("%v declared and not used", ln.Sym) 58 } 59 } 60 61 lineno = lno 62 if nerrors != 0 { 63 return 64 } 65 walkstmtlist(Curfn.Nbody.Slice()) 66 if Debug['W'] != 0 { 67 s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym) 68 dumplist(s, Curfn.Nbody) 69 } 70 71 heapmoves() 72 if Debug['W'] != 0 && Curfn.Func.Enter.Len() > 0 { 73 s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym) 74 dumplist(s, Curfn.Func.Enter) 75 } 76 } 77 78 func walkstmtlist(s []*Node) { 79 for i := range s { 80 s[i] = walkstmt(s[i]) 81 } 82 } 83 84 func samelist(a, b []*Node) bool { 85 if len(a) != len(b) { 86 return false 87 } 88 for i, n := range a { 89 if n != b[i] { 90 return false 91 } 92 } 93 return true 94 } 95 96 func paramoutheap(fn *Node) bool { 97 for _, ln := range fn.Func.Dcl { 98 switch ln.Class { 99 case PPARAMOUT: 100 if ln.isParamStackCopy() || ln.Addrtaken { 101 return true 102 } 103 104 case PAUTO: 105 // stop early - parameters are over 106 return false 107 } 108 } 109 110 return false 111 } 112 113 // adds "adjust" to all the argument locations for the call n. 114 // n must be a defer or go node that has already been walked. 115 func adjustargs(n *Node, adjust int) { 116 var arg *Node 117 var lhs *Node 118 119 callfunc := n.Left 120 for _, arg = range callfunc.List.Slice() { 121 if arg.Op != OAS { 122 yyerror("call arg not assignment") 123 } 124 lhs = arg.Left 125 if lhs.Op == ONAME { 126 // This is a temporary introduced by reorder1. 127 // The real store to the stack appears later in the arg list. 128 continue 129 } 130 131 if lhs.Op != OINDREGSP { 132 yyerror("call argument store does not use OINDREGSP") 133 } 134 135 // can't really check this in machine-indep code. 136 //if(lhs->val.u.reg != D_SP) 137 // yyerror("call arg assign not indreg(SP)"); 138 lhs.Xoffset += int64(adjust) 139 } 140 } 141 142 // The result of walkstmt MUST be assigned back to n, e.g. 143 // n.Left = walkstmt(n.Left) 144 func walkstmt(n *Node) *Node { 145 if n == nil { 146 return n 147 } 148 if n.IsStatic { // don't walk, generated by anylit. 149 return n 150 } 151 152 setlineno(n) 153 154 walkstmtlist(n.Ninit.Slice()) 155 156 switch n.Op { 157 default: 158 if n.Op == ONAME { 159 yyerror("%v is not a top level statement", n.Sym) 160 } else { 161 yyerror("%v is not a top level statement", n.Op) 162 } 163 Dump("nottop", n) 164 165 case OAS, 166 OASOP, 167 OAS2, 168 OAS2DOTTYPE, 169 OAS2RECV, 170 OAS2FUNC, 171 OAS2MAPR, 172 OCLOSE, 173 OCOPY, 174 OCALLMETH, 175 OCALLINTER, 176 OCALL, 177 OCALLFUNC, 178 ODELETE, 179 OSEND, 180 OPRINT, 181 OPRINTN, 182 OPANIC, 183 OEMPTY, 184 ORECOVER, 185 OGETG: 186 if n.Typecheck == 0 { 187 Fatalf("missing typecheck: %+v", n) 188 } 189 wascopy := n.Op == OCOPY 190 init := n.Ninit 191 n.Ninit.Set(nil) 192 n = walkexpr(n, &init) 193 n = addinit(n, init.Slice()) 194 if wascopy && n.Op == OCONVNOP { 195 n.Op = OEMPTY // don't leave plain values as statements. 196 } 197 198 // special case for a receive where we throw away 199 // the value received. 200 case ORECV: 201 if n.Typecheck == 0 { 202 Fatalf("missing typecheck: %+v", n) 203 } 204 init := n.Ninit 205 n.Ninit.Set(nil) 206 207 n.Left = walkexpr(n.Left, &init) 208 n = mkcall1(chanfn("chanrecv1", 2, n.Left.Type), nil, &init, typename(n.Left.Type), n.Left, nodnil()) 209 n = walkexpr(n, &init) 210 211 n = addinit(n, init.Slice()) 212 213 case OBREAK, 214 OCONTINUE, 215 OFALL, 216 OGOTO, 217 OLABEL, 218 ODCLCONST, 219 ODCLTYPE, 220 OCHECKNIL, 221 OVARKILL, 222 OVARLIVE: 223 break 224 225 case ODCL: 226 v := n.Left 227 if v.Class == PAUTOHEAP { 228 if compiling_runtime { 229 yyerror("%v escapes to heap, not allowed in runtime.", v) 230 } 231 if prealloc[v] == nil { 232 prealloc[v] = callnew(v.Type) 233 } 234 nn := nod(OAS, v.Name.Param.Heapaddr, prealloc[v]) 235 nn.Colas = true 236 nn = typecheck(nn, Etop) 237 return walkstmt(nn) 238 } 239 240 case OBLOCK: 241 walkstmtlist(n.List.Slice()) 242 243 case OXCASE: 244 yyerror("case statement out of place") 245 n.Op = OCASE 246 fallthrough 247 248 case OCASE: 249 n.Right = walkstmt(n.Right) 250 251 case ODEFER: 252 hasdefer = true 253 switch n.Left.Op { 254 case OPRINT, OPRINTN: 255 n.Left = walkprintfunc(n.Left, &n.Ninit) 256 257 case OCOPY: 258 n.Left = copyany(n.Left, &n.Ninit, true) 259 260 default: 261 n.Left = walkexpr(n.Left, &n.Ninit) 262 } 263 264 // make room for size & fn arguments. 265 adjustargs(n, 2*Widthptr) 266 267 case OFOR: 268 if n.Left != nil { 269 walkstmtlist(n.Left.Ninit.Slice()) 270 init := n.Left.Ninit 271 n.Left.Ninit.Set(nil) 272 n.Left = walkexpr(n.Left, &init) 273 n.Left = addinit(n.Left, init.Slice()) 274 } 275 276 n.Right = walkstmt(n.Right) 277 walkstmtlist(n.Nbody.Slice()) 278 279 case OIF: 280 n.Left = walkexpr(n.Left, &n.Ninit) 281 walkstmtlist(n.Nbody.Slice()) 282 walkstmtlist(n.Rlist.Slice()) 283 284 case OPROC: 285 switch n.Left.Op { 286 case OPRINT, OPRINTN: 287 n.Left = walkprintfunc(n.Left, &n.Ninit) 288 289 case OCOPY: 290 n.Left = copyany(n.Left, &n.Ninit, true) 291 292 default: 293 n.Left = walkexpr(n.Left, &n.Ninit) 294 } 295 296 // make room for size & fn arguments. 297 adjustargs(n, 2*Widthptr) 298 299 case ORETURN: 300 walkexprlist(n.List.Slice(), &n.Ninit) 301 if n.List.Len() == 0 { 302 break 303 } 304 if (Curfn.Type.FuncType().Outnamed && n.List.Len() > 1) || paramoutheap(Curfn) { 305 // assign to the function out parameters, 306 // so that reorder3 can fix up conflicts 307 var rl []*Node 308 309 var cl Class 310 for _, ln := range Curfn.Func.Dcl { 311 cl = ln.Class 312 if cl == PAUTO || cl == PAUTOHEAP { 313 break 314 } 315 if cl == PPARAMOUT { 316 if ln.isParamStackCopy() { 317 ln = walkexpr(typecheck(nod(OIND, ln.Name.Param.Heapaddr, nil), Erv), nil) 318 } 319 rl = append(rl, ln) 320 } 321 } 322 323 if got, want := n.List.Len(), len(rl); got != want { 324 // order should have rewritten multi-value function calls 325 // with explicit OAS2FUNC nodes. 326 Fatalf("expected %v return arguments, have %v", want, got) 327 } 328 329 if samelist(rl, n.List.Slice()) { 330 // special return in disguise 331 n.List.Set(nil) 332 333 break 334 } 335 336 // move function calls out, to make reorder3's job easier. 337 walkexprlistsafe(n.List.Slice(), &n.Ninit) 338 339 ll := ascompatee(n.Op, rl, n.List.Slice(), &n.Ninit) 340 n.List.Set(reorder3(ll)) 341 break 342 } 343 344 ll := ascompatte(n.Op, nil, false, Curfn.Type.Results(), n.List.Slice(), 1, &n.Ninit) 345 n.List.Set(ll) 346 347 case ORETJMP: 348 break 349 350 case OSELECT: 351 walkselect(n) 352 353 case OSWITCH: 354 walkswitch(n) 355 356 case ORANGE: 357 walkrange(n) 358 359 case OXFALL: 360 yyerror("fallthrough statement out of place") 361 n.Op = OFALL 362 } 363 364 if n.Op == ONAME { 365 Fatalf("walkstmt ended up with name: %+v", n) 366 } 367 return n 368 } 369 370 func isSmallMakeSlice(n *Node) bool { 371 if n.Op != OMAKESLICE { 372 return false 373 } 374 l := n.Left 375 r := n.Right 376 if r == nil { 377 r = l 378 } 379 t := n.Type 380 381 return smallintconst(l) && smallintconst(r) && (t.Elem().Width == 0 || r.Int64() < (1<<16)/t.Elem().Width) 382 } 383 384 // walk the whole tree of the body of an 385 // expression or simple statement. 386 // the types expressions are calculated. 387 // compile-time constants are evaluated. 388 // complex side effects like statements are appended to init 389 func walkexprlist(s []*Node, init *Nodes) { 390 for i := range s { 391 s[i] = walkexpr(s[i], init) 392 } 393 } 394 395 func walkexprlistsafe(s []*Node, init *Nodes) { 396 for i, n := range s { 397 s[i] = safeexpr(n, init) 398 s[i] = walkexpr(s[i], init) 399 } 400 } 401 402 func walkexprlistcheap(s []*Node, init *Nodes) { 403 for i, n := range s { 404 s[i] = cheapexpr(n, init) 405 s[i] = walkexpr(s[i], init) 406 } 407 } 408 409 // Build name of function for interface conversion. 410 // Not all names are possible 411 // (e.g., we'll never generate convE2E or convE2I or convI2E). 412 func convFuncName(from, to *Type) string { 413 tkind := to.iet() 414 switch from.iet() { 415 case 'I': 416 switch tkind { 417 case 'I': 418 return "convI2I" 419 } 420 case 'T': 421 switch tkind { 422 case 'E': 423 return "convT2E" 424 case 'I': 425 return "convT2I" 426 } 427 } 428 Fatalf("unknown conv func %c2%c", from.iet(), to.iet()) 429 panic("unreachable") 430 } 431 432 // The result of walkexpr MUST be assigned back to n, e.g. 433 // n.Left = walkexpr(n.Left, init) 434 func walkexpr(n *Node, init *Nodes) *Node { 435 if n == nil { 436 return n 437 } 438 439 if init == &n.Ninit { 440 // not okay to use n->ninit when walking n, 441 // because we might replace n with some other node 442 // and would lose the init list. 443 Fatalf("walkexpr init == &n->ninit") 444 } 445 446 if n.Ninit.Len() != 0 { 447 walkstmtlist(n.Ninit.Slice()) 448 init.AppendNodes(&n.Ninit) 449 } 450 451 lno := setlineno(n) 452 453 if Debug['w'] > 1 { 454 Dump("walk-before", n) 455 } 456 457 if n.Typecheck != 1 { 458 Fatalf("missed typecheck: %+v", n) 459 } 460 461 if n.Op == ONAME && n.Class == PAUTOHEAP { 462 nn := nod(OIND, n.Name.Param.Heapaddr, nil) 463 nn = typecheck(nn, Erv) 464 nn = walkexpr(nn, init) 465 nn.Left.NonNil = true 466 return nn 467 } 468 469 opswitch: 470 switch n.Op { 471 default: 472 Dump("walk", n) 473 Fatalf("walkexpr: switch 1 unknown op %+S", n) 474 475 case OTYPE, 476 ONONAME, 477 OINDREGSP, 478 OEMPTY, 479 OGETG: 480 481 case ONOT, 482 OMINUS, 483 OPLUS, 484 OCOM, 485 OREAL, 486 OIMAG, 487 ODOTMETH, 488 ODOTINTER: 489 n.Left = walkexpr(n.Left, init) 490 491 case OIND: 492 n.Left = walkexpr(n.Left, init) 493 494 case ODOT: 495 usefield(n) 496 n.Left = walkexpr(n.Left, init) 497 498 case ODOTPTR: 499 usefield(n) 500 if n.Op == ODOTPTR && n.Left.Type.Elem().Width == 0 { 501 // No actual copy will be generated, so emit an explicit nil check. 502 n.Left = cheapexpr(n.Left, init) 503 504 checknil(n.Left, init) 505 } 506 507 n.Left = walkexpr(n.Left, init) 508 509 case OEFACE: 510 n.Left = walkexpr(n.Left, init) 511 n.Right = walkexpr(n.Right, init) 512 513 case OSPTR, OITAB, OIDATA: 514 n.Left = walkexpr(n.Left, init) 515 516 case OLEN, OCAP: 517 n.Left = walkexpr(n.Left, init) 518 519 // replace len(*[10]int) with 10. 520 // delayed until now to preserve side effects. 521 t := n.Left.Type 522 523 if t.IsPtr() { 524 t = t.Elem() 525 } 526 if t.IsArray() { 527 safeexpr(n.Left, init) 528 nodconst(n, n.Type, t.NumElem()) 529 n.Typecheck = 1 530 } 531 532 case OLSH, ORSH: 533 n.Left = walkexpr(n.Left, init) 534 n.Right = walkexpr(n.Right, init) 535 t := n.Left.Type 536 n.Bounded = bounded(n.Right, 8*t.Width) 537 if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) { 538 Warn("shift bounds check elided") 539 } 540 541 case OAND, 542 OSUB, 543 OHMUL, 544 OMUL, 545 OLT, 546 OLE, 547 OGE, 548 OGT, 549 OADD, 550 OOR, 551 OXOR: 552 n.Left = walkexpr(n.Left, init) 553 n.Right = walkexpr(n.Right, init) 554 555 case OCOMPLEX: 556 // Use results from call expression as arguments for complex. 557 if n.Left == nil && n.Right == nil { 558 n.Left = n.List.First() 559 n.Right = n.List.Second() 560 } 561 n.Left = walkexpr(n.Left, init) 562 n.Right = walkexpr(n.Right, init) 563 564 case OEQ, ONE: 565 n.Left = walkexpr(n.Left, init) 566 n.Right = walkexpr(n.Right, init) 567 568 // Disable safemode while compiling this code: the code we 569 // generate internally can refer to unsafe.Pointer. 570 // In this case it can happen if we need to generate an == 571 // for a struct containing a reflect.Value, which itself has 572 // an unexported field of type unsafe.Pointer. 573 old_safemode := safemode 574 safemode = false 575 n = walkcompare(n, init) 576 safemode = old_safemode 577 578 case OANDAND, OOROR: 579 n.Left = walkexpr(n.Left, init) 580 581 // cannot put side effects from n.Right on init, 582 // because they cannot run before n.Left is checked. 583 // save elsewhere and store on the eventual n.Right. 584 var ll Nodes 585 586 n.Right = walkexpr(n.Right, &ll) 587 n.Right = addinit(n.Right, ll.Slice()) 588 n = walkinrange(n, init) 589 590 case OPRINT, OPRINTN: 591 walkexprlist(n.List.Slice(), init) 592 n = walkprint(n, init) 593 594 case OPANIC: 595 n = mkcall("gopanic", nil, init, n.Left) 596 597 case ORECOVER: 598 n = mkcall("gorecover", n.Type, init, nod(OADDR, nodfp, nil)) 599 600 case OLITERAL: 601 n.Addable = true 602 603 case OCLOSUREVAR, OCFUNC: 604 n.Addable = true 605 606 case ONAME: 607 n.Addable = true 608 609 case OCALLINTER: 610 usemethod(n) 611 t := n.Left.Type 612 if n.List.Len() != 0 && n.List.First().Op == OAS { 613 break 614 } 615 n.Left = walkexpr(n.Left, init) 616 walkexprlist(n.List.Slice(), init) 617 ll := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) 618 n.List.Set(reorder1(ll)) 619 620 case OCALLFUNC: 621 if n.Left.Op == OCLOSURE { 622 // Transform direct call of a closure to call of a normal function. 623 // transformclosure already did all preparation work. 624 625 // Prepend captured variables to argument list. 626 n.List.Prepend(n.Left.Func.Enter.Slice()...) 627 628 n.Left.Func.Enter.Set(nil) 629 630 // Replace OCLOSURE with ONAME/PFUNC. 631 n.Left = n.Left.Func.Closure.Func.Nname 632 633 // Update type of OCALLFUNC node. 634 // Output arguments had not changed, but their offsets could. 635 if n.Left.Type.Results().NumFields() == 1 { 636 n.Type = n.Left.Type.Results().Field(0).Type 637 } else { 638 n.Type = n.Left.Type.Results() 639 } 640 } 641 642 t := n.Left.Type 643 if n.List.Len() != 0 && n.List.First().Op == OAS { 644 break 645 } 646 647 n.Left = walkexpr(n.Left, init) 648 walkexprlist(n.List.Slice(), init) 649 650 ll := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) 651 n.List.Set(reorder1(ll)) 652 653 case OCALLMETH: 654 t := n.Left.Type 655 if n.List.Len() != 0 && n.List.First().Op == OAS { 656 break 657 } 658 n.Left = walkexpr(n.Left, init) 659 walkexprlist(n.List.Slice(), init) 660 ll := ascompatte(n.Op, n, false, t.Recvs(), []*Node{n.Left.Left}, 0, init) 661 lr := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) 662 ll = append(ll, lr...) 663 n.Left.Left = nil 664 ullmancalc(n.Left) 665 n.List.Set(reorder1(ll)) 666 667 case OAS: 668 init.AppendNodes(&n.Ninit) 669 670 n.Left = walkexpr(n.Left, init) 671 n.Left = safeexpr(n.Left, init) 672 673 if oaslit(n, init) { 674 break 675 } 676 677 if n.Right == nil { 678 // TODO(austin): Check all "implicit zeroing" 679 break 680 } 681 682 if !instrumenting && iszero(n.Right) { 683 break 684 } 685 686 switch n.Right.Op { 687 default: 688 n.Right = walkexpr(n.Right, init) 689 690 case ORECV: 691 // x = <-c; n.Left is x, n.Right.Left is c. 692 // orderstmt made sure x is addressable. 693 n.Right.Left = walkexpr(n.Right.Left, init) 694 695 n1 := nod(OADDR, n.Left, nil) 696 r := n.Right.Left // the channel 697 n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1) 698 n = walkexpr(n, init) 699 break opswitch 700 701 case OAPPEND: 702 // x = append(...) 703 r := n.Right 704 if r.Type.Elem().NotInHeap { 705 yyerror("%v is go:notinheap; heap allocation disallowed", r.Type.Elem()) 706 } 707 if r.Isddd { 708 r = appendslice(r, init) // also works for append(slice, string). 709 } else { 710 r = walkappend(r, init, n) 711 } 712 n.Right = r 713 if r.Op == OAPPEND { 714 // Left in place for back end. 715 // Do not add a new write barrier. 716 break opswitch 717 } 718 // Otherwise, lowered for race detector. 719 // Treat as ordinary assignment. 720 } 721 722 if n.Left != nil && n.Right != nil { 723 static := n.IsStatic 724 n = convas(n, init) 725 n.IsStatic = static 726 } 727 728 case OAS2: 729 init.AppendNodes(&n.Ninit) 730 walkexprlistsafe(n.List.Slice(), init) 731 walkexprlistsafe(n.Rlist.Slice(), init) 732 ll := ascompatee(OAS, n.List.Slice(), n.Rlist.Slice(), init) 733 ll = reorder3(ll) 734 n = liststmt(ll) 735 736 // a,b,... = fn() 737 case OAS2FUNC: 738 init.AppendNodes(&n.Ninit) 739 740 r := n.Rlist.First() 741 walkexprlistsafe(n.List.Slice(), init) 742 r = walkexpr(r, init) 743 744 if isIntrinsicCall(r) { 745 n.Rlist.Set1(r) 746 break 747 } 748 init.Append(r) 749 750 ll := ascompatet(n.Op, n.List, r.Type) 751 n = liststmt(ll) 752 753 // x, y = <-c 754 // orderstmt made sure x is addressable. 755 case OAS2RECV: 756 init.AppendNodes(&n.Ninit) 757 758 r := n.Rlist.First() 759 walkexprlistsafe(n.List.Slice(), init) 760 r.Left = walkexpr(r.Left, init) 761 var n1 *Node 762 if isblank(n.List.First()) { 763 n1 = nodnil() 764 } else { 765 n1 = nod(OADDR, n.List.First(), nil) 766 } 767 n1.Etype = 1 // addr does not escape 768 fn := chanfn("chanrecv2", 2, r.Left.Type) 769 ok := n.List.Second() 770 call := mkcall1(fn, ok.Type, init, typename(r.Left.Type), r.Left, n1) 771 n = nod(OAS, ok, call) 772 n = typecheck(n, Etop) 773 774 // a,b = m[i]; 775 case OAS2MAPR: 776 init.AppendNodes(&n.Ninit) 777 778 r := n.Rlist.First() 779 walkexprlistsafe(n.List.Slice(), init) 780 r.Left = walkexpr(r.Left, init) 781 r.Right = walkexpr(r.Right, init) 782 t := r.Left.Type 783 784 _, p := mapaccessfast(t) 785 var key *Node 786 if p != "" { 787 // fast versions take key by value 788 key = r.Right 789 } else { 790 // standard version takes key by reference 791 // orderexpr made sure key is addressable. 792 key = nod(OADDR, r.Right, nil) 793 p = "mapaccess2" 794 } 795 796 // from: 797 // a,b = m[i] 798 // to: 799 // var,b = mapaccess2*(t, m, i) 800 // a = *var 801 a := n.List.First() 802 803 if w := t.Val().Width; w <= 1024 { // 1024 must match ../../../../runtime/hashmap.go:maxZero 804 fn := mapfn(p, t) 805 r = mkcall1(fn, fn.Type.Results(), init, typename(t), r.Left, key) 806 } else { 807 fn := mapfn("mapaccess2_fat", t) 808 z := zeroaddr(w) 809 r = mkcall1(fn, fn.Type.Results(), init, typename(t), r.Left, key, z) 810 } 811 812 // mapaccess2* returns a typed bool, but due to spec changes, 813 // the boolean result of i.(T) is now untyped so we make it the 814 // same type as the variable on the lhs. 815 if ok := n.List.Second(); !isblank(ok) && ok.Type.IsBoolean() { 816 r.Type.Field(1).Type = ok.Type 817 } 818 n.Rlist.Set1(r) 819 n.Op = OAS2FUNC 820 821 // don't generate a = *var if a is _ 822 if !isblank(a) { 823 var_ := temp(ptrto(t.Val())) 824 var_.Typecheck = 1 825 var_.NonNil = true // mapaccess always returns a non-nil pointer 826 n.List.SetIndex(0, var_) 827 n = walkexpr(n, init) 828 init.Append(n) 829 n = nod(OAS, a, nod(OIND, var_, nil)) 830 } 831 832 n = typecheck(n, Etop) 833 n = walkexpr(n, init) 834 835 case ODELETE: 836 init.AppendNodes(&n.Ninit) 837 map_ := n.List.First() 838 key := n.List.Second() 839 map_ = walkexpr(map_, init) 840 key = walkexpr(key, init) 841 842 // orderstmt made sure key is addressable. 843 key = nod(OADDR, key, nil) 844 845 t := map_.Type 846 n = mkcall1(mapfndel("mapdelete", t), nil, init, typename(t), map_, key) 847 848 case OAS2DOTTYPE: 849 walkexprlistsafe(n.List.Slice(), init) 850 e := n.Rlist.First() // i.(T) 851 e.Left = walkexpr(e.Left, init) 852 853 case ODOTTYPE, ODOTTYPE2: 854 n.Left = walkexpr(n.Left, init) 855 856 case OCONVIFACE: 857 n.Left = walkexpr(n.Left, init) 858 859 // Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped. 860 if isdirectiface(n.Left.Type) { 861 var t *Node 862 if n.Type.IsEmptyInterface() { 863 t = typename(n.Left.Type) 864 } else { 865 t = itabname(n.Left.Type, n.Type) 866 } 867 l := nod(OEFACE, t, n.Left) 868 l.Type = n.Type 869 l.Typecheck = n.Typecheck 870 n = l 871 break 872 } 873 874 if staticbytes == nil { 875 staticbytes = newname(Pkglookup("staticbytes", Runtimepkg)) 876 staticbytes.Class = PEXTERN 877 staticbytes.Type = typArray(Types[TUINT8], 256) 878 zerobase = newname(Pkglookup("zerobase", Runtimepkg)) 879 zerobase.Class = PEXTERN 880 zerobase.Type = Types[TUINTPTR] 881 } 882 883 // Optimize convT2{E,I} for many cases in which T is not pointer-shaped, 884 // by using an existing addressable value identical to n.Left 885 // or creating one on the stack. 886 var value *Node 887 switch { 888 case n.Left.Type.Size() == 0: 889 // n.Left is zero-sized. Use zerobase. 890 value = zerobase 891 case n.Left.Type.IsBoolean() || (n.Left.Type.Size() == 1 && n.Left.Type.IsInteger()): 892 // n.Left is a bool/byte. Use staticbytes[n.Left]. 893 value = nod(OINDEX, staticbytes, byteindex(n.Left)) 894 value.Bounded = true 895 case n.Left.Class == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly: 896 // n.Left is a readonly global; use it directly. 897 value = n.Left 898 case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024: 899 // n.Left does not escape. Use a stack temporary initialized to n.Left. 900 value = temp(n.Left.Type) 901 init.Append(typecheck(nod(OAS, value, n.Left), Etop)) 902 } 903 904 if value != nil { 905 // Value is identical to n.Left. 906 // Construct the interface directly: {type/itab, &value}. 907 var t *Node 908 if n.Type.IsEmptyInterface() { 909 t = typename(n.Left.Type) 910 } else { 911 t = itabname(n.Left.Type, n.Type) 912 } 913 l := nod(OEFACE, t, typecheck(nod(OADDR, value, nil), Erv)) 914 l.Type = n.Type 915 l.Typecheck = n.Typecheck 916 n = l 917 break 918 } 919 920 // Implement interface to empty interface conversion. 921 // tmp = i.itab 922 // if tmp != nil { 923 // tmp = tmp.type 924 // } 925 // e = iface{tmp, i.data} 926 if n.Type.IsEmptyInterface() && n.Left.Type.IsInterface() && !n.Left.Type.IsEmptyInterface() { 927 // Evaluate the input interface. 928 c := temp(n.Left.Type) 929 init.Append(nod(OAS, c, n.Left)) 930 931 // Get the itab out of the interface. 932 tmp := temp(ptrto(Types[TUINT8])) 933 init.Append(nod(OAS, tmp, typecheck(nod(OITAB, c, nil), Erv))) 934 935 // Get the type out of the itab. 936 nif := nod(OIF, typecheck(nod(ONE, tmp, nodnil()), Erv), nil) 937 nif.Nbody.Set1(nod(OAS, tmp, itabType(tmp))) 938 init.Append(nif) 939 940 // Build the result. 941 e := nod(OEFACE, tmp, ifaceData(c, ptrto(Types[TUINT8]))) 942 e.Type = n.Type // assign type manually, typecheck doesn't understand OEFACE. 943 e.Typecheck = 1 944 n = e 945 break 946 } 947 948 var ll []*Node 949 if n.Type.IsEmptyInterface() { 950 if !n.Left.Type.IsInterface() { 951 ll = append(ll, typename(n.Left.Type)) 952 } 953 } else { 954 if n.Left.Type.IsInterface() { 955 ll = append(ll, typename(n.Type)) 956 } else { 957 ll = append(ll, itabname(n.Left.Type, n.Type)) 958 } 959 } 960 961 if n.Left.Type.IsInterface() { 962 ll = append(ll, n.Left) 963 } else { 964 // regular types are passed by reference to avoid C vararg calls 965 // orderexpr arranged for n.Left to be a temporary for all 966 // the conversions it could see. comparison of an interface 967 // with a non-interface, especially in a switch on interface value 968 // with non-interface cases, is not visible to orderstmt, so we 969 // have to fall back on allocating a temp here. 970 if islvalue(n.Left) { 971 ll = append(ll, nod(OADDR, n.Left, nil)) 972 } else { 973 ll = append(ll, nod(OADDR, copyexpr(n.Left, n.Left.Type, init), nil)) 974 } 975 dowidth(n.Left.Type) 976 } 977 978 fn := syslook(convFuncName(n.Left.Type, n.Type)) 979 fn = substArgTypes(fn, n.Left.Type, n.Type) 980 dowidth(fn.Type) 981 n = nod(OCALL, fn, nil) 982 n.List.Set(ll) 983 n = typecheck(n, Erv) 984 n = walkexpr(n, init) 985 986 case OCONV, OCONVNOP: 987 if Thearch.LinkArch.Family == sys.ARM || Thearch.LinkArch.Family == sys.MIPS { 988 if n.Left.Type.IsFloat() { 989 if n.Type.Etype == TINT64 { 990 n = mkcall("float64toint64", n.Type, init, conv(n.Left, Types[TFLOAT64])) 991 break 992 } 993 994 if n.Type.Etype == TUINT64 { 995 n = mkcall("float64touint64", n.Type, init, conv(n.Left, Types[TFLOAT64])) 996 break 997 } 998 } 999 1000 if n.Type.IsFloat() { 1001 if n.Left.Type.Etype == TINT64 { 1002 n = conv(mkcall("int64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TINT64])), n.Type) 1003 break 1004 } 1005 1006 if n.Left.Type.Etype == TUINT64 { 1007 n = conv(mkcall("uint64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TUINT64])), n.Type) 1008 break 1009 } 1010 } 1011 } 1012 1013 if Thearch.LinkArch.Family == sys.I386 { 1014 if n.Left.Type.IsFloat() { 1015 if n.Type.Etype == TINT64 { 1016 n = mkcall("float64toint64", n.Type, init, conv(n.Left, Types[TFLOAT64])) 1017 break 1018 } 1019 1020 if n.Type.Etype == TUINT64 { 1021 n = mkcall("float64touint64", n.Type, init, conv(n.Left, Types[TFLOAT64])) 1022 break 1023 } 1024 if n.Type.Etype == TUINT32 || n.Type.Etype == TUINT || n.Type.Etype == TUINTPTR { 1025 n = mkcall("float64touint32", n.Type, init, conv(n.Left, Types[TFLOAT64])) 1026 break 1027 } 1028 } 1029 if n.Type.IsFloat() { 1030 if n.Left.Type.Etype == TINT64 { 1031 n = conv(mkcall("int64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TINT64])), n.Type) 1032 break 1033 } 1034 1035 if n.Left.Type.Etype == TUINT64 { 1036 n = conv(mkcall("uint64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TUINT64])), n.Type) 1037 break 1038 } 1039 if n.Left.Type.Etype == TUINT32 || n.Left.Type.Etype == TUINT || n.Left.Type.Etype == TUINTPTR { 1040 n = conv(mkcall("uint32tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TUINT32])), n.Type) 1041 break 1042 } 1043 } 1044 } 1045 1046 n.Left = walkexpr(n.Left, init) 1047 1048 case OANDNOT: 1049 n.Left = walkexpr(n.Left, init) 1050 n.Op = OAND 1051 n.Right = nod(OCOM, n.Right, nil) 1052 n.Right = typecheck(n.Right, Erv) 1053 n.Right = walkexpr(n.Right, init) 1054 1055 case ODIV, OMOD: 1056 n.Left = walkexpr(n.Left, init) 1057 n.Right = walkexpr(n.Right, init) 1058 1059 // rewrite complex div into function call. 1060 et := n.Left.Type.Etype 1061 1062 if isComplex[et] && n.Op == ODIV { 1063 t := n.Type 1064 n = mkcall("complex128div", Types[TCOMPLEX128], init, conv(n.Left, Types[TCOMPLEX128]), conv(n.Right, Types[TCOMPLEX128])) 1065 n = conv(n, t) 1066 break 1067 } 1068 1069 // Nothing to do for float divisions. 1070 if isFloat[et] { 1071 break 1072 } 1073 1074 // Try rewriting as shifts or magic multiplies. 1075 n = walkdiv(n, init) 1076 1077 // rewrite 64-bit div and mod into function calls 1078 // on 32-bit architectures. 1079 switch n.Op { 1080 case OMOD, ODIV: 1081 if Widthreg >= 8 || (et != TUINT64 && et != TINT64) { 1082 break opswitch 1083 } 1084 var fn string 1085 if et == TINT64 { 1086 fn = "int64" 1087 } else { 1088 fn = "uint64" 1089 } 1090 if n.Op == ODIV { 1091 fn += "div" 1092 } else { 1093 fn += "mod" 1094 } 1095 n = mkcall(fn, n.Type, init, conv(n.Left, Types[et]), conv(n.Right, Types[et])) 1096 } 1097 1098 case OINDEX: 1099 n.Left = walkexpr(n.Left, init) 1100 1101 // save the original node for bounds checking elision. 1102 // If it was a ODIV/OMOD walk might rewrite it. 1103 r := n.Right 1104 1105 n.Right = walkexpr(n.Right, init) 1106 1107 // if range of type cannot exceed static array bound, 1108 // disable bounds check. 1109 if n.Bounded { 1110 break 1111 } 1112 t := n.Left.Type 1113 if t != nil && t.IsPtr() { 1114 t = t.Elem() 1115 } 1116 if t.IsArray() { 1117 n.Bounded = bounded(r, t.NumElem()) 1118 if Debug['m'] != 0 && n.Bounded && !Isconst(n.Right, CTINT) { 1119 Warn("index bounds check elided") 1120 } 1121 if smallintconst(n.Right) && !n.Bounded { 1122 yyerror("index out of bounds") 1123 } 1124 } else if Isconst(n.Left, CTSTR) { 1125 n.Bounded = bounded(r, int64(len(n.Left.Val().U.(string)))) 1126 if Debug['m'] != 0 && n.Bounded && !Isconst(n.Right, CTINT) { 1127 Warn("index bounds check elided") 1128 } 1129 if smallintconst(n.Right) && !n.Bounded { 1130 yyerror("index out of bounds") 1131 } 1132 } 1133 1134 if Isconst(n.Right, CTINT) { 1135 if n.Right.Val().U.(*Mpint).CmpInt64(0) < 0 || n.Right.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 { 1136 yyerror("index out of bounds") 1137 } 1138 } 1139 1140 case OINDEXMAP: 1141 // Replace m[k] with *map{access1,assign}(maptype, m, &k) 1142 n.Left = walkexpr(n.Left, init) 1143 n.Right = walkexpr(n.Right, init) 1144 map_ := n.Left 1145 key := n.Right 1146 t := map_.Type 1147 if n.Etype == 1 { 1148 // This m[k] expression is on the left-hand side of an assignment. 1149 // orderexpr made sure key is addressable. 1150 key = nod(OADDR, key, nil) 1151 n = mkcall1(mapfn("mapassign", t), nil, init, typename(t), map_, key) 1152 } else { 1153 // m[k] is not the target of an assignment. 1154 p, _ := mapaccessfast(t) 1155 if p == "" { 1156 // standard version takes key by reference. 1157 // orderexpr made sure key is addressable. 1158 key = nod(OADDR, key, nil) 1159 p = "mapaccess1" 1160 } 1161 1162 if w := t.Val().Width; w <= 1024 { // 1024 must match ../../../../runtime/hashmap.go:maxZero 1163 n = mkcall1(mapfn(p, t), ptrto(t.Val()), init, typename(t), map_, key) 1164 } else { 1165 p = "mapaccess1_fat" 1166 z := zeroaddr(w) 1167 n = mkcall1(mapfn(p, t), ptrto(t.Val()), init, typename(t), map_, key, z) 1168 } 1169 } 1170 n.Type = ptrto(t.Val()) 1171 n.NonNil = true // mapaccess1* and mapassign always return non-nil pointers. 1172 n = nod(OIND, n, nil) 1173 n.Type = t.Val() 1174 n.Typecheck = 1 1175 1176 case ORECV: 1177 Fatalf("walkexpr ORECV") // should see inside OAS only 1178 1179 case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: 1180 n.Left = walkexpr(n.Left, init) 1181 low, high, max := n.SliceBounds() 1182 low = walkexpr(low, init) 1183 if low != nil && iszero(low) { 1184 // Reduce x[0:j] to x[:j] and x[0:j:k] to x[:j:k]. 1185 low = nil 1186 } 1187 high = walkexpr(high, init) 1188 max = walkexpr(max, init) 1189 n.SetSliceBounds(low, high, max) 1190 if n.Op.IsSlice3() { 1191 if max != nil && max.Op == OCAP && samesafeexpr(n.Left, max.Left) { 1192 // Reduce x[i:j:cap(x)] to x[i:j]. 1193 if n.Op == OSLICE3 { 1194 n.Op = OSLICE 1195 } else { 1196 n.Op = OSLICEARR 1197 } 1198 n = reduceSlice(n) 1199 } 1200 } else { 1201 n = reduceSlice(n) 1202 } 1203 1204 case OADDR: 1205 n.Left = walkexpr(n.Left, init) 1206 1207 case ONEW: 1208 if n.Esc == EscNone { 1209 if n.Type.Elem().Width >= 1<<16 { 1210 Fatalf("large ONEW with EscNone: %v", n) 1211 } 1212 r := temp(n.Type.Elem()) 1213 r = nod(OAS, r, nil) // zero temp 1214 r = typecheck(r, Etop) 1215 init.Append(r) 1216 r = nod(OADDR, r.Left, nil) 1217 r = typecheck(r, Erv) 1218 n = r 1219 } else { 1220 n = callnew(n.Type.Elem()) 1221 } 1222 1223 case OCMPSTR: 1224 // s + "badgerbadgerbadger" == "badgerbadgerbadger" 1225 if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && n.Left.List.Len() == 2 && Isconst(n.Left.List.Second(), CTSTR) && strlit(n.Right) == strlit(n.Left.List.Second()) { 1226 // TODO(marvin): Fix Node.EType type union. 1227 r := nod(Op(n.Etype), nod(OLEN, n.Left.List.First(), nil), nodintconst(0)) 1228 r = typecheck(r, Erv) 1229 r = walkexpr(r, init) 1230 r.Type = n.Type 1231 n = r 1232 break 1233 } 1234 1235 // Rewrite comparisons to short constant strings as length+byte-wise comparisons. 1236 var cs, ncs *Node // const string, non-const string 1237 switch { 1238 case Isconst(n.Left, CTSTR) && Isconst(n.Right, CTSTR): 1239 // ignore; will be constant evaluated 1240 case Isconst(n.Left, CTSTR): 1241 cs = n.Left 1242 ncs = n.Right 1243 case Isconst(n.Right, CTSTR): 1244 cs = n.Right 1245 ncs = n.Left 1246 } 1247 if cs != nil { 1248 cmp := Op(n.Etype) 1249 // maxRewriteLen was chosen empirically. 1250 // It is the value that minimizes cmd/go file size 1251 // across most architectures. 1252 // See the commit description for CL 26758 for details. 1253 maxRewriteLen := 6 1254 var and Op 1255 switch cmp { 1256 case OEQ: 1257 and = OANDAND 1258 case ONE: 1259 and = OOROR 1260 default: 1261 // Don't do byte-wise comparisons for <, <=, etc. 1262 // They're fairly complicated. 1263 // Length-only checks are ok, though. 1264 maxRewriteLen = 0 1265 } 1266 if s := cs.Val().U.(string); len(s) <= maxRewriteLen { 1267 if len(s) > 0 { 1268 ncs = safeexpr(ncs, init) 1269 } 1270 // TODO(marvin): Fix Node.EType type union. 1271 r := nod(cmp, nod(OLEN, ncs, nil), nodintconst(int64(len(s)))) 1272 for i := 0; i < len(s); i++ { 1273 cb := nodintconst(int64(s[i])) 1274 ncb := nod(OINDEX, ncs, nodintconst(int64(i))) 1275 r = nod(and, r, nod(cmp, ncb, cb)) 1276 } 1277 r = typecheck(r, Erv) 1278 r = walkexpr(r, init) 1279 r.Type = n.Type 1280 n = r 1281 break 1282 } 1283 } 1284 1285 var r *Node 1286 // TODO(marvin): Fix Node.EType type union. 1287 if Op(n.Etype) == OEQ || Op(n.Etype) == ONE { 1288 // prepare for rewrite below 1289 n.Left = cheapexpr(n.Left, init) 1290 n.Right = cheapexpr(n.Right, init) 1291 1292 r = mkcall("eqstring", Types[TBOOL], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING])) 1293 1294 // quick check of len before full compare for == or != 1295 // eqstring assumes that the lengths are equal 1296 // TODO(marvin): Fix Node.EType type union. 1297 if Op(n.Etype) == OEQ { 1298 // len(left) == len(right) && eqstring(left, right) 1299 r = nod(OANDAND, nod(OEQ, nod(OLEN, n.Left, nil), nod(OLEN, n.Right, nil)), r) 1300 } else { 1301 // len(left) != len(right) || !eqstring(left, right) 1302 r = nod(ONOT, r, nil) 1303 r = nod(OOROR, nod(ONE, nod(OLEN, n.Left, nil), nod(OLEN, n.Right, nil)), r) 1304 } 1305 1306 r = typecheck(r, Erv) 1307 r = walkexpr(r, nil) 1308 } else { 1309 // sys_cmpstring(s1, s2) :: 0 1310 r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING])) 1311 // TODO(marvin): Fix Node.EType type union. 1312 r = nod(Op(n.Etype), r, nodintconst(0)) 1313 } 1314 1315 r = typecheck(r, Erv) 1316 if !n.Type.IsBoolean() { 1317 Fatalf("cmp %v", n.Type) 1318 } 1319 r.Type = n.Type 1320 n = r 1321 1322 case OADDSTR: 1323 n = addstr(n, init) 1324 1325 case OAPPEND: 1326 // order should make sure we only see OAS(node, OAPPEND), which we handle above. 1327 Fatalf("append outside assignment") 1328 1329 case OCOPY: 1330 n = copyany(n, init, instrumenting && !compiling_runtime) 1331 1332 // cannot use chanfn - closechan takes any, not chan any 1333 case OCLOSE: 1334 fn := syslook("closechan") 1335 1336 fn = substArgTypes(fn, n.Left.Type) 1337 n = mkcall1(fn, nil, init, n.Left) 1338 1339 case OMAKECHAN: 1340 n = mkcall1(chanfn("makechan", 1, n.Type), n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64])) 1341 1342 case OMAKEMAP: 1343 t := n.Type 1344 1345 a := nodnil() // hmap buffer 1346 r := nodnil() // bucket buffer 1347 if n.Esc == EscNone { 1348 // Allocate hmap buffer on stack. 1349 var_ := temp(hmap(t)) 1350 1351 a = nod(OAS, var_, nil) // zero temp 1352 a = typecheck(a, Etop) 1353 init.Append(a) 1354 a = nod(OADDR, var_, nil) 1355 1356 // Allocate one bucket on stack. 1357 // Maximum key/value size is 128 bytes, larger objects 1358 // are stored with an indirection. So max bucket size is 2048+eps. 1359 var_ = temp(mapbucket(t)) 1360 1361 r = nod(OAS, var_, nil) // zero temp 1362 r = typecheck(r, Etop) 1363 init.Append(r) 1364 r = nod(OADDR, var_, nil) 1365 } 1366 1367 fn := syslook("makemap") 1368 fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Val()) 1369 n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r) 1370 1371 case OMAKESLICE: 1372 l := n.Left 1373 r := n.Right 1374 if r == nil { 1375 r = safeexpr(l, init) 1376 l = r 1377 } 1378 t := n.Type 1379 if n.Esc == EscNone { 1380 if !isSmallMakeSlice(n) { 1381 Fatalf("non-small OMAKESLICE with EscNone: %v", n) 1382 } 1383 // var arr [r]T 1384 // n = arr[:l] 1385 t = typArray(t.Elem(), nonnegintconst(r)) // [r]T 1386 var_ := temp(t) 1387 a := nod(OAS, var_, nil) // zero temp 1388 a = typecheck(a, Etop) 1389 init.Append(a) 1390 r := nod(OSLICE, var_, nil) // arr[:l] 1391 r.SetSliceBounds(nil, l, nil) 1392 r = conv(r, n.Type) // in case n.Type is named. 1393 r = typecheck(r, Erv) 1394 r = walkexpr(r, init) 1395 n = r 1396 } else { 1397 // n escapes; set up a call to makeslice. 1398 // When len and cap can fit into int, use makeslice instead of 1399 // makeslice64, which is faster and shorter on 32 bit platforms. 1400 1401 if t.Elem().NotInHeap { 1402 yyerror("%v is go:notinheap; heap allocation disallowed", t.Elem()) 1403 } 1404 1405 len, cap := l, r 1406 1407 fnname := "makeslice64" 1408 argtype := Types[TINT64] 1409 1410 // typechecking guarantees that TIDEAL len/cap are positive and fit in an int. 1411 // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT 1412 // will be handled by the negative range checks in makeslice during runtime. 1413 if (len.Type.IsKind(TIDEAL) || maxintval[len.Type.Etype].Cmp(maxintval[TUINT]) <= 0) && 1414 (cap.Type.IsKind(TIDEAL) || maxintval[cap.Type.Etype].Cmp(maxintval[TUINT]) <= 0) { 1415 fnname = "makeslice" 1416 argtype = Types[TINT] 1417 } 1418 1419 fn := syslook(fnname) 1420 fn = substArgTypes(fn, t.Elem()) // any-1 1421 n = mkcall1(fn, t, init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)) 1422 } 1423 1424 case ORUNESTR: 1425 a := nodnil() 1426 if n.Esc == EscNone { 1427 t := typArray(Types[TUINT8], 4) 1428 var_ := temp(t) 1429 a = nod(OADDR, var_, nil) 1430 } 1431 1432 // intstring(*[4]byte, rune) 1433 n = mkcall("intstring", n.Type, init, a, conv(n.Left, Types[TINT64])) 1434 1435 case OARRAYBYTESTR: 1436 a := nodnil() 1437 if n.Esc == EscNone { 1438 // Create temporary buffer for string on stack. 1439 t := typArray(Types[TUINT8], tmpstringbufsize) 1440 1441 a = nod(OADDR, temp(t), nil) 1442 } 1443 1444 // slicebytetostring(*[32]byte, []byte) string; 1445 n = mkcall("slicebytetostring", n.Type, init, a, n.Left) 1446 1447 // slicebytetostringtmp([]byte) string; 1448 case OARRAYBYTESTRTMP: 1449 n.Left = walkexpr(n.Left, init) 1450 1451 if !instrumenting { 1452 // Let the backend handle OARRAYBYTESTRTMP directly 1453 // to avoid a function call to slicebytetostringtmp. 1454 break 1455 } 1456 1457 n = mkcall("slicebytetostringtmp", n.Type, init, n.Left) 1458 1459 // slicerunetostring(*[32]byte, []rune) string; 1460 case OARRAYRUNESTR: 1461 a := nodnil() 1462 1463 if n.Esc == EscNone { 1464 // Create temporary buffer for string on stack. 1465 t := typArray(Types[TUINT8], tmpstringbufsize) 1466 1467 a = nod(OADDR, temp(t), nil) 1468 } 1469 1470 n = mkcall("slicerunetostring", n.Type, init, a, n.Left) 1471 1472 // stringtoslicebyte(*32[byte], string) []byte; 1473 case OSTRARRAYBYTE: 1474 a := nodnil() 1475 1476 if n.Esc == EscNone { 1477 // Create temporary buffer for slice on stack. 1478 t := typArray(Types[TUINT8], tmpstringbufsize) 1479 1480 a = nod(OADDR, temp(t), nil) 1481 } 1482 1483 n = mkcall("stringtoslicebyte", n.Type, init, a, conv(n.Left, Types[TSTRING])) 1484 1485 case OSTRARRAYBYTETMP: 1486 // []byte(string) conversion that creates a slice 1487 // referring to the actual string bytes. 1488 // This conversion is handled later by the backend and 1489 // is only for use by internal compiler optimizations 1490 // that know that the slice won't be mutated. 1491 // The only such case today is: 1492 // for i, c := range []byte(string) 1493 n.Left = walkexpr(n.Left, init) 1494 1495 // stringtoslicerune(*[32]rune, string) []rune 1496 case OSTRARRAYRUNE: 1497 a := nodnil() 1498 1499 if n.Esc == EscNone { 1500 // Create temporary buffer for slice on stack. 1501 t := typArray(Types[TINT32], tmpstringbufsize) 1502 1503 a = nod(OADDR, temp(t), nil) 1504 } 1505 1506 n = mkcall("stringtoslicerune", n.Type, init, a, n.Left) 1507 1508 // ifaceeq(i1 any-1, i2 any-2) (ret bool); 1509 case OCMPIFACE: 1510 if !eqtype(n.Left.Type, n.Right.Type) { 1511 Fatalf("ifaceeq %v %v %v", n.Op, n.Left.Type, n.Right.Type) 1512 } 1513 var fn *Node 1514 if n.Left.Type.IsEmptyInterface() { 1515 fn = syslook("efaceeq") 1516 } else { 1517 fn = syslook("ifaceeq") 1518 } 1519 1520 n.Right = cheapexpr(n.Right, init) 1521 n.Left = cheapexpr(n.Left, init) 1522 fn = substArgTypes(fn, n.Right.Type, n.Left.Type) 1523 r := mkcall1(fn, n.Type, init, n.Left, n.Right) 1524 // TODO(marvin): Fix Node.EType type union. 1525 if Op(n.Etype) == ONE { 1526 r = nod(ONOT, r, nil) 1527 } 1528 1529 // check itable/type before full compare. 1530 // TODO(marvin): Fix Node.EType type union. 1531 if Op(n.Etype) == OEQ { 1532 r = nod(OANDAND, nod(OEQ, nod(OITAB, n.Left, nil), nod(OITAB, n.Right, nil)), r) 1533 } else { 1534 r = nod(OOROR, nod(ONE, nod(OITAB, n.Left, nil), nod(OITAB, n.Right, nil)), r) 1535 } 1536 r = typecheck(r, Erv) 1537 r = walkexpr(r, init) 1538 r.Type = n.Type 1539 n = r 1540 1541 case OARRAYLIT, OSLICELIT, OMAPLIT, OSTRUCTLIT, OPTRLIT: 1542 if isStaticCompositeLiteral(n) { 1543 // n can be directly represented in the read-only data section. 1544 // Make direct reference to the static data. See issue 12841. 1545 vstat := staticname(n.Type) 1546 vstat.Name.Readonly = true 1547 fixedlit(inInitFunction, initKindStatic, n, vstat, init) 1548 n = vstat 1549 n = typecheck(n, Erv) 1550 break 1551 } 1552 var_ := temp(n.Type) 1553 anylit(n, var_, init) 1554 n = var_ 1555 1556 case OSEND: 1557 n1 := n.Right 1558 n1 = assignconv(n1, n.Left.Type.Elem(), "chan send") 1559 n1 = walkexpr(n1, init) 1560 n1 = nod(OADDR, n1, nil) 1561 n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1) 1562 1563 case OCLOSURE: 1564 n = walkclosure(n, init) 1565 1566 case OCALLPART: 1567 n = walkpartialcall(n, init) 1568 } 1569 1570 // Expressions that are constant at run time but not 1571 // considered const by the language spec are not turned into 1572 // constants until walk. For example, if n is y%1 == 0, the 1573 // walk of y%1 may have replaced it by 0. 1574 // Check whether n with its updated args is itself now a constant. 1575 t := n.Type 1576 1577 evconst(n) 1578 n.Type = t 1579 if n.Op == OLITERAL { 1580 n = typecheck(n, Erv) 1581 } 1582 1583 ullmancalc(n) 1584 1585 if Debug['w'] != 0 && n != nil { 1586 Dump("walk", n) 1587 } 1588 1589 lineno = lno 1590 return n 1591 } 1592 1593 // TODO(josharian): combine this with its caller and simplify 1594 func reduceSlice(n *Node) *Node { 1595 low, high, max := n.SliceBounds() 1596 if high != nil && high.Op == OLEN && samesafeexpr(n.Left, high.Left) { 1597 // Reduce x[i:len(x)] to x[i:]. 1598 high = nil 1599 } 1600 n.SetSliceBounds(low, high, max) 1601 if (n.Op == OSLICE || n.Op == OSLICESTR) && low == nil && high == nil { 1602 // Reduce x[:] to x. 1603 if Debug_slice > 0 { 1604 Warn("slice: omit slice operation") 1605 } 1606 return n.Left 1607 } 1608 return n 1609 } 1610 1611 func ascompatee1(op Op, l *Node, r *Node, init *Nodes) *Node { 1612 // convas will turn map assigns into function calls, 1613 // making it impossible for reorder3 to work. 1614 n := nod(OAS, l, r) 1615 1616 if l.Op == OINDEXMAP { 1617 return n 1618 } 1619 1620 return convas(n, init) 1621 } 1622 1623 func ascompatee(op Op, nl, nr []*Node, init *Nodes) []*Node { 1624 // check assign expression list to 1625 // a expression list. called in 1626 // expr-list = expr-list 1627 1628 // ensure order of evaluation for function calls 1629 for i := range nl { 1630 nl[i] = safeexpr(nl[i], init) 1631 } 1632 for i1 := range nr { 1633 nr[i1] = safeexpr(nr[i1], init) 1634 } 1635 1636 var nn []*Node 1637 i := 0 1638 for ; i < len(nl); i++ { 1639 if i >= len(nr) { 1640 break 1641 } 1642 // Do not generate 'x = x' during return. See issue 4014. 1643 if op == ORETURN && samesafeexpr(nl[i], nr[i]) { 1644 continue 1645 } 1646 nn = append(nn, ascompatee1(op, nl[i], nr[i], init)) 1647 } 1648 1649 // cannot happen: caller checked that lists had same length 1650 if i < len(nl) || i < len(nr) { 1651 var nln, nrn Nodes 1652 nln.Set(nl) 1653 nrn.Set(nr) 1654 yyerror("error in shape across %+v %v %+v / %d %d [%s]", nln, op, nrn, len(nl), len(nr), Curfn.Func.Nname.Sym.Name) 1655 } 1656 return nn 1657 } 1658 1659 // l is an lv and rt is the type of an rv 1660 // return 1 if this implies a function call 1661 // evaluating the lv or a function call 1662 // in the conversion of the types 1663 func fncall(l *Node, rt *Type) bool { 1664 if l.Ullman >= UINF || l.Op == OINDEXMAP { 1665 return true 1666 } 1667 var r Node 1668 if needwritebarrier(l, &r) { 1669 return true 1670 } 1671 if eqtype(l.Type, rt) { 1672 return false 1673 } 1674 return true 1675 } 1676 1677 // check assign type list to 1678 // a expression list. called in 1679 // expr-list = func() 1680 func ascompatet(op Op, nl Nodes, nr *Type) []*Node { 1681 r, saver := iterFields(nr) 1682 1683 var nn, mm Nodes 1684 var ullmanOverflow bool 1685 var i int 1686 for i = 0; i < nl.Len(); i++ { 1687 if r == nil { 1688 break 1689 } 1690 l := nl.Index(i) 1691 if isblank(l) { 1692 r = saver.Next() 1693 continue 1694 } 1695 1696 // any lv that causes a fn call must be 1697 // deferred until all the return arguments 1698 // have been pulled from the output arguments 1699 if fncall(l, r.Type) { 1700 tmp := temp(r.Type) 1701 tmp = typecheck(tmp, Erv) 1702 a := nod(OAS, l, tmp) 1703 a = convas(a, &mm) 1704 mm.Append(a) 1705 l = tmp 1706 } 1707 1708 a := nod(OAS, l, nodarg(r, 0)) 1709 a = convas(a, &nn) 1710 ullmancalc(a) 1711 if a.Ullman >= UINF { 1712 Dump("ascompatet ucount", a) 1713 ullmanOverflow = true 1714 } 1715 1716 nn.Append(a) 1717 r = saver.Next() 1718 } 1719 1720 if i < nl.Len() || r != nil { 1721 yyerror("ascompatet: assignment count mismatch: %d = %d", nl.Len(), nr.NumFields()) 1722 } 1723 1724 if ullmanOverflow { 1725 Fatalf("ascompatet: too many function calls evaluating parameters") 1726 } 1727 return append(nn.Slice(), mm.Slice()...) 1728 } 1729 1730 // package all the arguments that match a ... T parameter into a []T. 1731 func mkdotargslice(lr0, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) []*Node { 1732 esc := uint16(EscUnknown) 1733 if ddd != nil { 1734 esc = ddd.Esc 1735 } 1736 1737 tslice := typSlice(l.Type.Elem()) 1738 1739 var n *Node 1740 if len(lr0) == 0 { 1741 n = nodnil() 1742 n.Type = tslice 1743 } else { 1744 n = nod(OCOMPLIT, nil, typenod(tslice)) 1745 if ddd != nil && prealloc[ddd] != nil { 1746 prealloc[n] = prealloc[ddd] // temporary to use 1747 } 1748 n.List.Set(lr0) 1749 n.Esc = esc 1750 n = typecheck(n, Erv) 1751 if n.Type == nil { 1752 Fatalf("mkdotargslice: typecheck failed") 1753 } 1754 n = walkexpr(n, init) 1755 } 1756 1757 a := nod(OAS, nodarg(l, fp), n) 1758 nn = append(nn, convas(a, init)) 1759 return nn 1760 } 1761 1762 // helpers for shape errors 1763 func dumptypes(nl *Type, what string) string { 1764 s := "" 1765 for _, l := range nl.Fields().Slice() { 1766 if s != "" { 1767 s += ", " 1768 } 1769 s += fldconv(l, 0) 1770 } 1771 if s == "" { 1772 s = fmt.Sprintf("[no arguments %s]", what) 1773 } 1774 return s 1775 } 1776 1777 func dumpnodetypes(l []*Node, what string) string { 1778 s := "" 1779 for _, r := range l { 1780 if s != "" { 1781 s += ", " 1782 } 1783 s += r.Type.String() 1784 } 1785 if s == "" { 1786 s = fmt.Sprintf("[no arguments %s]", what) 1787 } 1788 return s 1789 } 1790 1791 // check assign expression list to 1792 // a type list. called in 1793 // return expr-list 1794 // func(expr-list) 1795 func ascompatte(op Op, call *Node, isddd bool, nl *Type, lr []*Node, fp int, init *Nodes) []*Node { 1796 lr0 := lr 1797 l, savel := iterFields(nl) 1798 var r *Node 1799 if len(lr) > 0 { 1800 r = lr[0] 1801 } 1802 var nn []*Node 1803 1804 // f(g()) where g has multiple return values 1805 if r != nil && len(lr) <= 1 && r.Type.IsFuncArgStruct() { 1806 // optimization - can do block copy 1807 if eqtypenoname(r.Type, nl) { 1808 arg := nodarg(nl, fp) 1809 r = nod(OCONVNOP, r, nil) 1810 r.Type = arg.Type 1811 nn = []*Node{convas(nod(OAS, arg, r), init)} 1812 goto ret 1813 } 1814 1815 // conversions involved. 1816 // copy into temporaries. 1817 var alist []*Node 1818 1819 for _, l := range r.Type.Fields().Slice() { 1820 tmp := temp(l.Type) 1821 alist = append(alist, tmp) 1822 } 1823 1824 a := nod(OAS2, nil, nil) 1825 a.List.Set(alist) 1826 a.Rlist.Set(lr) 1827 a = typecheck(a, Etop) 1828 a = walkstmt(a) 1829 init.Append(a) 1830 lr = alist 1831 r = lr[0] 1832 l, savel = iterFields(nl) 1833 } 1834 1835 for { 1836 if l != nil && l.Isddd { 1837 // the ddd parameter must be last 1838 ll := savel.Next() 1839 1840 if ll != nil { 1841 yyerror("... must be last argument") 1842 } 1843 1844 // special case -- 1845 // only if we are assigning a single ddd 1846 // argument to a ddd parameter then it is 1847 // passed through unencapsulated 1848 if r != nil && len(lr) <= 1 && isddd && eqtype(l.Type, r.Type) { 1849 a := nod(OAS, nodarg(l, fp), r) 1850 a = convas(a, init) 1851 nn = append(nn, a) 1852 break 1853 } 1854 1855 // normal case -- make a slice of all 1856 // remaining arguments and pass it to 1857 // the ddd parameter. 1858 nn = mkdotargslice(lr, nn, l, fp, init, call.Right) 1859 1860 break 1861 } 1862 1863 if l == nil || r == nil { 1864 if l != nil || r != nil { 1865 l1 := dumptypes(nl, "expected") 1866 l2 := dumpnodetypes(lr0, "given") 1867 if l != nil { 1868 yyerror("not enough arguments to %v\n\t%s\n\t%s", op, l1, l2) 1869 } else { 1870 yyerror("too many arguments to %v\n\t%s\n\t%s", op, l1, l2) 1871 } 1872 } 1873 1874 break 1875 } 1876 1877 a := nod(OAS, nodarg(l, fp), r) 1878 a = convas(a, init) 1879 nn = append(nn, a) 1880 1881 l = savel.Next() 1882 r = nil 1883 lr = lr[1:] 1884 if len(lr) > 0 { 1885 r = lr[0] 1886 } 1887 } 1888 1889 ret: 1890 for _, n := range nn { 1891 n.Typecheck = 1 1892 } 1893 return nn 1894 } 1895 1896 // generate code for print 1897 func walkprint(nn *Node, init *Nodes) *Node { 1898 var r *Node 1899 var n *Node 1900 var on *Node 1901 var t *Type 1902 var et EType 1903 1904 op := nn.Op 1905 all := nn.List 1906 var calls []*Node 1907 notfirst := false 1908 1909 // Hoist all the argument evaluation up before the lock. 1910 walkexprlistcheap(all.Slice(), init) 1911 1912 calls = append(calls, mkcall("printlock", nil, init)) 1913 for i1, n1 := range all.Slice() { 1914 if notfirst { 1915 calls = append(calls, mkcall("printsp", nil, init)) 1916 } 1917 1918 notfirst = op == OPRINTN 1919 1920 n = n1 1921 if n.Op == OLITERAL { 1922 switch n.Val().Ctype() { 1923 case CTRUNE: 1924 n = defaultlit(n, runetype) 1925 1926 case CTINT: 1927 n = defaultlit(n, Types[TINT64]) 1928 1929 case CTFLT: 1930 n = defaultlit(n, Types[TFLOAT64]) 1931 } 1932 } 1933 1934 if n.Op != OLITERAL && n.Type != nil && n.Type.Etype == TIDEAL { 1935 n = defaultlit(n, Types[TINT64]) 1936 } 1937 n = defaultlit(n, nil) 1938 all.SetIndex(i1, n) 1939 if n.Type == nil || n.Type.Etype == TFORW { 1940 continue 1941 } 1942 1943 t = n.Type 1944 et = n.Type.Etype 1945 if n.Type.IsInterface() { 1946 if n.Type.IsEmptyInterface() { 1947 on = syslook("printeface") 1948 } else { 1949 on = syslook("printiface") 1950 } 1951 on = substArgTypes(on, n.Type) // any-1 1952 } else if n.Type.IsPtr() || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR { 1953 on = syslook("printpointer") 1954 on = substArgTypes(on, n.Type) // any-1 1955 } else if n.Type.IsSlice() { 1956 on = syslook("printslice") 1957 on = substArgTypes(on, n.Type) // any-1 1958 } else if isInt[et] { 1959 if et == TUINT64 { 1960 if (t.Sym.Pkg == Runtimepkg || compiling_runtime) && t.Sym.Name == "hex" { 1961 on = syslook("printhex") 1962 } else { 1963 on = syslook("printuint") 1964 } 1965 } else { 1966 on = syslook("printint") 1967 } 1968 } else if isFloat[et] { 1969 on = syslook("printfloat") 1970 } else if isComplex[et] { 1971 on = syslook("printcomplex") 1972 } else if et == TBOOL { 1973 on = syslook("printbool") 1974 } else if et == TSTRING { 1975 on = syslook("printstring") 1976 } else { 1977 badtype(OPRINT, n.Type, nil) 1978 continue 1979 } 1980 1981 t = on.Type.Params().Field(0).Type 1982 1983 if !eqtype(t, n.Type) { 1984 n = nod(OCONV, n, nil) 1985 n.Type = t 1986 } 1987 1988 r = nod(OCALL, on, nil) 1989 r.List.Append(n) 1990 calls = append(calls, r) 1991 } 1992 1993 if op == OPRINTN { 1994 calls = append(calls, mkcall("printnl", nil, nil)) 1995 } 1996 1997 calls = append(calls, mkcall("printunlock", nil, init)) 1998 1999 typecheckslice(calls, Etop) 2000 walkexprlist(calls, init) 2001 2002 r = nod(OEMPTY, nil, nil) 2003 r = typecheck(r, Etop) 2004 r = walkexpr(r, init) 2005 r.Ninit.Set(calls) 2006 return r 2007 } 2008 2009 func callnew(t *Type) *Node { 2010 if t.NotInHeap { 2011 yyerror("%v is go:notinheap; heap allocation disallowed", t) 2012 } 2013 dowidth(t) 2014 fn := syslook("newobject") 2015 fn = substArgTypes(fn, t) 2016 v := mkcall1(fn, ptrto(t), nil, typename(t)) 2017 v.NonNil = true 2018 return v 2019 } 2020 2021 func iscallret(n *Node) bool { 2022 n = outervalue(n) 2023 return n.Op == OINDREGSP 2024 } 2025 2026 func isstack(n *Node) bool { 2027 n = outervalue(n) 2028 2029 // If n is *autotmp and autotmp = &foo, replace n with foo. 2030 // We introduce such temps when initializing struct literals. 2031 if n.Op == OIND && n.Left.Op == ONAME && n.Left.IsAutoTmp() { 2032 defn := n.Left.Name.Defn 2033 if defn != nil && defn.Op == OAS && defn.Right.Op == OADDR { 2034 n = defn.Right.Left 2035 } 2036 } 2037 2038 switch n.Op { 2039 case OINDREGSP: 2040 return true 2041 2042 case ONAME: 2043 switch n.Class { 2044 case PAUTO, PPARAM, PPARAMOUT: 2045 return true 2046 } 2047 } 2048 2049 return false 2050 } 2051 2052 // Do we need a write barrier for the assignment l = r? 2053 func needwritebarrier(l *Node, r *Node) bool { 2054 if !use_writebarrier { 2055 return false 2056 } 2057 2058 if l == nil || isblank(l) { 2059 return false 2060 } 2061 2062 // No write barrier for write of non-pointers. 2063 dowidth(l.Type) 2064 2065 if !haspointers(l.Type) { 2066 return false 2067 } 2068 2069 // No write barrier for write to stack. 2070 if isstack(l) { 2071 return false 2072 } 2073 2074 // No write barrier if this is a pointer to a go:notinheap 2075 // type, since the write barrier's inheap(ptr) check will fail. 2076 if l.Type.IsPtr() && l.Type.Elem().NotInHeap { 2077 return false 2078 } 2079 2080 // Implicit zeroing is still zeroing, so it needs write 2081 // barriers. In practice, these are all to stack variables 2082 // (even if isstack isn't smart enough to figure that out), so 2083 // they'll be eliminated by the backend. 2084 if r == nil { 2085 return true 2086 } 2087 2088 // Ignore no-op conversions when making decision. 2089 // Ensures that xp = unsafe.Pointer(&x) is treated 2090 // the same as xp = &x. 2091 for r.Op == OCONVNOP { 2092 r = r.Left 2093 } 2094 2095 // TODO: We can eliminate write barriers if we know *both* the 2096 // current and new content of the slot must already be shaded. 2097 // We know a pointer is shaded if it's nil, or points to 2098 // static data, a global (variable or function), or the stack. 2099 // The nil optimization could be particularly useful for 2100 // writes to just-allocated objects. Unfortunately, knowing 2101 // the "current" value of the slot requires flow analysis. 2102 2103 // No write barrier for storing address of stack values, 2104 // which are guaranteed only to be written to the stack. 2105 if r.Op == OADDR && isstack(r.Left) { 2106 return false 2107 } 2108 2109 // Otherwise, be conservative and use write barrier. 2110 return true 2111 } 2112 2113 func convas(n *Node, init *Nodes) *Node { 2114 if n.Op != OAS { 2115 Fatalf("convas: not OAS %v", n.Op) 2116 } 2117 2118 n.Typecheck = 1 2119 2120 var lt *Type 2121 var rt *Type 2122 if n.Left == nil || n.Right == nil { 2123 goto out 2124 } 2125 2126 lt = n.Left.Type 2127 rt = n.Right.Type 2128 if lt == nil || rt == nil { 2129 goto out 2130 } 2131 2132 if isblank(n.Left) { 2133 n.Right = defaultlit(n.Right, nil) 2134 goto out 2135 } 2136 2137 if !eqtype(lt, rt) { 2138 n.Right = assignconv(n.Right, lt, "assignment") 2139 n.Right = walkexpr(n.Right, init) 2140 } 2141 2142 out: 2143 ullmancalc(n) 2144 return n 2145 } 2146 2147 // from ascompat[te] 2148 // evaluating actual function arguments. 2149 // f(a,b) 2150 // if there is exactly one function expr, 2151 // then it is done first. otherwise must 2152 // make temp variables 2153 func reorder1(all []*Node) []*Node { 2154 c := 0 // function calls 2155 t := 0 // total parameters 2156 2157 for _, n := range all { 2158 t++ 2159 ullmancalc(n) 2160 if n.Ullman >= UINF { 2161 c++ 2162 } 2163 } 2164 2165 if c == 0 || t == 1 { 2166 return all 2167 } 2168 2169 var g []*Node // fncalls assigned to tempnames 2170 var f *Node // last fncall assigned to stack 2171 var r []*Node // non fncalls and tempnames assigned to stack 2172 d := 0 2173 var a *Node 2174 for _, n := range all { 2175 if n.Ullman < UINF { 2176 r = append(r, n) 2177 continue 2178 } 2179 2180 d++ 2181 if d == c { 2182 f = n 2183 continue 2184 } 2185 2186 // make assignment of fncall to tempname 2187 a = temp(n.Right.Type) 2188 2189 a = nod(OAS, a, n.Right) 2190 g = append(g, a) 2191 2192 // put normal arg assignment on list 2193 // with fncall replaced by tempname 2194 n.Right = a.Left 2195 2196 r = append(r, n) 2197 } 2198 2199 if f != nil { 2200 g = append(g, f) 2201 } 2202 return append(g, r...) 2203 } 2204 2205 // from ascompat[ee] 2206 // a,b = c,d 2207 // simultaneous assignment. there cannot 2208 // be later use of an earlier lvalue. 2209 // 2210 // function calls have been removed. 2211 func reorder3(all []*Node) []*Node { 2212 var l *Node 2213 2214 // If a needed expression may be affected by an 2215 // earlier assignment, make an early copy of that 2216 // expression and use the copy instead. 2217 var early []*Node 2218 2219 var mapinit Nodes 2220 for i, n := range all { 2221 l = n.Left 2222 2223 // Save subexpressions needed on left side. 2224 // Drill through non-dereferences. 2225 for { 2226 if l.Op == ODOT || l.Op == OPAREN { 2227 l = l.Left 2228 continue 2229 } 2230 2231 if l.Op == OINDEX && l.Left.Type.IsArray() { 2232 l.Right = reorder3save(l.Right, all, i, &early) 2233 l = l.Left 2234 continue 2235 } 2236 2237 break 2238 } 2239 2240 switch l.Op { 2241 default: 2242 Fatalf("reorder3 unexpected lvalue %#v", l.Op) 2243 2244 case ONAME: 2245 break 2246 2247 case OINDEX, OINDEXMAP: 2248 l.Left = reorder3save(l.Left, all, i, &early) 2249 l.Right = reorder3save(l.Right, all, i, &early) 2250 if l.Op == OINDEXMAP { 2251 all[i] = convas(all[i], &mapinit) 2252 } 2253 2254 case OIND, ODOTPTR: 2255 l.Left = reorder3save(l.Left, all, i, &early) 2256 } 2257 2258 // Save expression on right side. 2259 all[i].Right = reorder3save(all[i].Right, all, i, &early) 2260 } 2261 2262 early = append(mapinit.Slice(), early...) 2263 return append(early, all...) 2264 } 2265 2266 // if the evaluation of *np would be affected by the 2267 // assignments in all up to but not including the ith assignment, 2268 // copy into a temporary during *early and 2269 // replace *np with that temp. 2270 // The result of reorder3save MUST be assigned back to n, e.g. 2271 // n.Left = reorder3save(n.Left, all, i, early) 2272 func reorder3save(n *Node, all []*Node, i int, early *[]*Node) *Node { 2273 if !aliased(n, all, i) { 2274 return n 2275 } 2276 2277 q := temp(n.Type) 2278 q = nod(OAS, q, n) 2279 q = typecheck(q, Etop) 2280 *early = append(*early, q) 2281 return q.Left 2282 } 2283 2284 // what's the outer value that a write to n affects? 2285 // outer value means containing struct or array. 2286 func outervalue(n *Node) *Node { 2287 for { 2288 if n.Op == OXDOT { 2289 Fatalf("OXDOT in walk") 2290 } 2291 if n.Op == ODOT || n.Op == OPAREN || n.Op == OCONVNOP { 2292 n = n.Left 2293 continue 2294 } 2295 2296 if n.Op == OINDEX && n.Left.Type != nil && n.Left.Type.IsArray() { 2297 n = n.Left 2298 continue 2299 } 2300 2301 break 2302 } 2303 2304 return n 2305 } 2306 2307 // Is it possible that the computation of n might be 2308 // affected by writes in as up to but not including the ith element? 2309 func aliased(n *Node, all []*Node, i int) bool { 2310 if n == nil { 2311 return false 2312 } 2313 2314 // Treat all fields of a struct as referring to the whole struct. 2315 // We could do better but we would have to keep track of the fields. 2316 for n.Op == ODOT { 2317 n = n.Left 2318 } 2319 2320 // Look for obvious aliasing: a variable being assigned 2321 // during the all list and appearing in n. 2322 // Also record whether there are any writes to main memory. 2323 // Also record whether there are any writes to variables 2324 // whose addresses have been taken. 2325 memwrite := 0 2326 2327 varwrite := 0 2328 var a *Node 2329 for _, an := range all[:i] { 2330 a = outervalue(an.Left) 2331 2332 for a.Op == ODOT { 2333 a = a.Left 2334 } 2335 2336 if a.Op != ONAME { 2337 memwrite = 1 2338 continue 2339 } 2340 2341 switch n.Class { 2342 default: 2343 varwrite = 1 2344 continue 2345 2346 case PAUTO, PPARAM, PPARAMOUT: 2347 if n.Addrtaken { 2348 varwrite = 1 2349 continue 2350 } 2351 2352 if vmatch2(a, n) { 2353 // Direct hit. 2354 return true 2355 } 2356 } 2357 } 2358 2359 // The variables being written do not appear in n. 2360 // However, n might refer to computed addresses 2361 // that are being written. 2362 2363 // If no computed addresses are affected by the writes, no aliasing. 2364 if memwrite == 0 && varwrite == 0 { 2365 return false 2366 } 2367 2368 // If n does not refer to computed addresses 2369 // (that is, if n only refers to variables whose addresses 2370 // have not been taken), no aliasing. 2371 if varexpr(n) { 2372 return false 2373 } 2374 2375 // Otherwise, both the writes and n refer to computed memory addresses. 2376 // Assume that they might conflict. 2377 return true 2378 } 2379 2380 // does the evaluation of n only refer to variables 2381 // whose addresses have not been taken? 2382 // (and no other memory) 2383 func varexpr(n *Node) bool { 2384 if n == nil { 2385 return true 2386 } 2387 2388 switch n.Op { 2389 case OLITERAL: 2390 return true 2391 2392 case ONAME: 2393 switch n.Class { 2394 case PAUTO, PPARAM, PPARAMOUT: 2395 if !n.Addrtaken { 2396 return true 2397 } 2398 } 2399 2400 return false 2401 2402 case OADD, 2403 OSUB, 2404 OOR, 2405 OXOR, 2406 OMUL, 2407 ODIV, 2408 OMOD, 2409 OLSH, 2410 ORSH, 2411 OAND, 2412 OANDNOT, 2413 OPLUS, 2414 OMINUS, 2415 OCOM, 2416 OPAREN, 2417 OANDAND, 2418 OOROR, 2419 OCONV, 2420 OCONVNOP, 2421 OCONVIFACE, 2422 ODOTTYPE: 2423 return varexpr(n.Left) && varexpr(n.Right) 2424 2425 case ODOT: // but not ODOTPTR 2426 // Should have been handled in aliased. 2427 Fatalf("varexpr unexpected ODOT") 2428 } 2429 2430 // Be conservative. 2431 return false 2432 } 2433 2434 // is the name l mentioned in r? 2435 func vmatch2(l *Node, r *Node) bool { 2436 if r == nil { 2437 return false 2438 } 2439 switch r.Op { 2440 // match each right given left 2441 case ONAME: 2442 return l == r 2443 2444 case OLITERAL: 2445 return false 2446 } 2447 2448 if vmatch2(l, r.Left) { 2449 return true 2450 } 2451 if vmatch2(l, r.Right) { 2452 return true 2453 } 2454 for _, n := range r.List.Slice() { 2455 if vmatch2(l, n) { 2456 return true 2457 } 2458 } 2459 return false 2460 } 2461 2462 // is any name mentioned in l also mentioned in r? 2463 // called by sinit.go 2464 func vmatch1(l *Node, r *Node) bool { 2465 // isolate all left sides 2466 if l == nil || r == nil { 2467 return false 2468 } 2469 switch l.Op { 2470 case ONAME: 2471 switch l.Class { 2472 case PPARAM, PAUTO: 2473 break 2474 2475 // assignment to non-stack variable 2476 // must be delayed if right has function calls. 2477 default: 2478 if r.Ullman >= UINF { 2479 return true 2480 } 2481 } 2482 2483 return vmatch2(l, r) 2484 2485 case OLITERAL: 2486 return false 2487 } 2488 2489 if vmatch1(l.Left, r) { 2490 return true 2491 } 2492 if vmatch1(l.Right, r) { 2493 return true 2494 } 2495 for _, n := range l.List.Slice() { 2496 if vmatch1(n, r) { 2497 return true 2498 } 2499 } 2500 return false 2501 } 2502 2503 // paramstoheap returns code to allocate memory for heap-escaped parameters 2504 // and to copy non-result prameters' values from the stack. 2505 // If out is true, then code is also produced to zero-initialize their 2506 // stack memory addresses. 2507 func paramstoheap(params *Type) []*Node { 2508 var nn []*Node 2509 for _, t := range params.Fields().Slice() { 2510 // For precise stacks, the garbage collector assumes results 2511 // are always live, so zero them always. 2512 if params.StructType().Funarg == FunargResults { 2513 // Defer might stop a panic and show the 2514 // return values as they exist at the time of panic. 2515 // Make sure to zero them on entry to the function. 2516 nn = append(nn, nod(OAS, nodarg(t, 1), nil)) 2517 } 2518 2519 v := t.Nname 2520 if v != nil && v.Sym != nil && strings.HasPrefix(v.Sym.Name, "~r") { // unnamed result 2521 v = nil 2522 } 2523 if v == nil { 2524 continue 2525 } 2526 2527 if stackcopy := v.Name.Param.Stackcopy; stackcopy != nil { 2528 nn = append(nn, walkstmt(nod(ODCL, v, nil))) 2529 if stackcopy.Class == PPARAM { 2530 nn = append(nn, walkstmt(typecheck(nod(OAS, v, stackcopy), Etop))) 2531 } 2532 } 2533 } 2534 2535 return nn 2536 } 2537 2538 // returnsfromheap returns code to copy values for heap-escaped parameters 2539 // back to the stack. 2540 func returnsfromheap(params *Type) []*Node { 2541 var nn []*Node 2542 for _, t := range params.Fields().Slice() { 2543 v := t.Nname 2544 if v == nil { 2545 continue 2546 } 2547 if stackcopy := v.Name.Param.Stackcopy; stackcopy != nil && stackcopy.Class == PPARAMOUT { 2548 nn = append(nn, walkstmt(typecheck(nod(OAS, stackcopy, v), Etop))) 2549 } 2550 } 2551 2552 return nn 2553 } 2554 2555 // heapmoves generates code to handle migrating heap-escaped parameters 2556 // between the stack and the heap. The generated code is added to Curfn's 2557 // Enter and Exit lists. 2558 func heapmoves() { 2559 lno := lineno 2560 lineno = Curfn.Pos 2561 nn := paramstoheap(Curfn.Type.Recvs()) 2562 nn = append(nn, paramstoheap(Curfn.Type.Params())...) 2563 nn = append(nn, paramstoheap(Curfn.Type.Results())...) 2564 Curfn.Func.Enter.Append(nn...) 2565 lineno = Curfn.Func.Endlineno 2566 Curfn.Func.Exit.Append(returnsfromheap(Curfn.Type.Results())...) 2567 lineno = lno 2568 } 2569 2570 func vmkcall(fn *Node, t *Type, init *Nodes, va []*Node) *Node { 2571 if fn.Type == nil || fn.Type.Etype != TFUNC { 2572 Fatalf("mkcall %v %v", fn, fn.Type) 2573 } 2574 2575 n := fn.Type.Params().NumFields() 2576 2577 r := nod(OCALL, fn, nil) 2578 r.List.Set(va[:n]) 2579 if fn.Type.Results().NumFields() > 0 { 2580 r = typecheck(r, Erv|Efnstruct) 2581 } else { 2582 r = typecheck(r, Etop) 2583 } 2584 r = walkexpr(r, init) 2585 r.Type = t 2586 return r 2587 } 2588 2589 func mkcall(name string, t *Type, init *Nodes, args ...*Node) *Node { 2590 return vmkcall(syslook(name), t, init, args) 2591 } 2592 2593 func mkcall1(fn *Node, t *Type, init *Nodes, args ...*Node) *Node { 2594 return vmkcall(fn, t, init, args) 2595 } 2596 2597 func conv(n *Node, t *Type) *Node { 2598 if eqtype(n.Type, t) { 2599 return n 2600 } 2601 n = nod(OCONV, n, nil) 2602 n.Type = t 2603 n = typecheck(n, Erv) 2604 return n 2605 } 2606 2607 // byteindex converts n, which is byte-sized, to a uint8. 2608 // We cannot use conv, because we allow converting bool to uint8 here, 2609 // which is forbidden in user code. 2610 func byteindex(n *Node) *Node { 2611 if eqtype(n.Type, Types[TUINT8]) { 2612 return n 2613 } 2614 n = nod(OCONV, n, nil) 2615 n.Type = Types[TUINT8] 2616 n.Typecheck = 1 2617 return n 2618 } 2619 2620 func chanfn(name string, n int, t *Type) *Node { 2621 if !t.IsChan() { 2622 Fatalf("chanfn %v", t) 2623 } 2624 fn := syslook(name) 2625 switch n { 2626 default: 2627 Fatalf("chanfn %d", n) 2628 case 1: 2629 fn = substArgTypes(fn, t.Elem()) 2630 case 2: 2631 fn = substArgTypes(fn, t.Elem(), t.Elem()) 2632 } 2633 return fn 2634 } 2635 2636 func mapfn(name string, t *Type) *Node { 2637 if !t.IsMap() { 2638 Fatalf("mapfn %v", t) 2639 } 2640 fn := syslook(name) 2641 fn = substArgTypes(fn, t.Key(), t.Val(), t.Key(), t.Val()) 2642 return fn 2643 } 2644 2645 func mapfndel(name string, t *Type) *Node { 2646 if !t.IsMap() { 2647 Fatalf("mapfn %v", t) 2648 } 2649 fn := syslook(name) 2650 fn = substArgTypes(fn, t.Key(), t.Val(), t.Key()) 2651 return fn 2652 } 2653 2654 // mapaccessfast returns the names of the fast map access runtime routines for t. 2655 func mapaccessfast(t *Type) (access1, access2 string) { 2656 // Check ../../runtime/hashmap.go:maxValueSize before changing. 2657 if t.Val().Width > 128 { 2658 return "", "" 2659 } 2660 switch algtype(t.Key()) { 2661 case AMEM32: 2662 return "mapaccess1_fast32", "mapaccess2_fast32" 2663 case AMEM64: 2664 return "mapaccess1_fast64", "mapaccess2_fast64" 2665 case ASTRING: 2666 return "mapaccess1_faststr", "mapaccess2_faststr" 2667 } 2668 return "", "" 2669 } 2670 2671 func writebarrierfn(name string, l *Type, r *Type) *Node { 2672 fn := syslook(name) 2673 fn = substArgTypes(fn, l, r) 2674 return fn 2675 } 2676 2677 func addstr(n *Node, init *Nodes) *Node { 2678 // orderexpr rewrote OADDSTR to have a list of strings. 2679 c := n.List.Len() 2680 2681 if c < 2 { 2682 yyerror("addstr count %d too small", c) 2683 } 2684 2685 buf := nodnil() 2686 if n.Esc == EscNone { 2687 sz := int64(0) 2688 for _, n1 := range n.List.Slice() { 2689 if n1.Op == OLITERAL { 2690 sz += int64(len(n1.Val().U.(string))) 2691 } 2692 } 2693 2694 // Don't allocate the buffer if the result won't fit. 2695 if sz < tmpstringbufsize { 2696 // Create temporary buffer for result string on stack. 2697 t := typArray(Types[TUINT8], tmpstringbufsize) 2698 2699 buf = nod(OADDR, temp(t), nil) 2700 } 2701 } 2702 2703 // build list of string arguments 2704 args := []*Node{buf} 2705 for _, n2 := range n.List.Slice() { 2706 args = append(args, conv(n2, Types[TSTRING])) 2707 } 2708 2709 var fn string 2710 if c <= 5 { 2711 // small numbers of strings use direct runtime helpers. 2712 // note: orderexpr knows this cutoff too. 2713 fn = fmt.Sprintf("concatstring%d", c) 2714 } else { 2715 // large numbers of strings are passed to the runtime as a slice. 2716 fn = "concatstrings" 2717 2718 t := typSlice(Types[TSTRING]) 2719 slice := nod(OCOMPLIT, nil, typenod(t)) 2720 if prealloc[n] != nil { 2721 prealloc[slice] = prealloc[n] 2722 } 2723 slice.List.Set(args[1:]) // skip buf arg 2724 args = []*Node{buf, slice} 2725 slice.Esc = EscNone 2726 } 2727 2728 cat := syslook(fn) 2729 r := nod(OCALL, cat, nil) 2730 r.List.Set(args) 2731 r = typecheck(r, Erv) 2732 r = walkexpr(r, init) 2733 r.Type = n.Type 2734 2735 return r 2736 } 2737 2738 // expand append(l1, l2...) to 2739 // init { 2740 // s := l1 2741 // n := len(s) + len(l2) 2742 // // Compare as uint so growslice can panic on overflow. 2743 // if uint(n) > uint(cap(s)) { 2744 // s = growslice(s, n) 2745 // } 2746 // s = s[:n] 2747 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) 2748 // } 2749 // s 2750 // 2751 // l2 is allowed to be a string. 2752 func appendslice(n *Node, init *Nodes) *Node { 2753 walkexprlistsafe(n.List.Slice(), init) 2754 2755 // walkexprlistsafe will leave OINDEX (s[n]) alone if both s 2756 // and n are name or literal, but those may index the slice we're 2757 // modifying here. Fix explicitly. 2758 ls := n.List.Slice() 2759 for i1, n1 := range ls { 2760 ls[i1] = cheapexpr(n1, init) 2761 } 2762 2763 l1 := n.List.First() 2764 l2 := n.List.Second() 2765 2766 var l []*Node 2767 2768 // var s []T 2769 s := temp(l1.Type) 2770 l = append(l, nod(OAS, s, l1)) // s = l1 2771 2772 // n := len(s) + len(l2) 2773 nn := temp(Types[TINT]) 2774 l = append(l, nod(OAS, nn, nod(OADD, nod(OLEN, s, nil), nod(OLEN, l2, nil)))) 2775 2776 // if uint(n) > uint(cap(s)) 2777 nif := nod(OIF, nil, nil) 2778 nif.Left = nod(OGT, nod(OCONV, nn, nil), nod(OCONV, nod(OCAP, s, nil), nil)) 2779 nif.Left.Left.Type = Types[TUINT] 2780 nif.Left.Right.Type = Types[TUINT] 2781 2782 // instantiate growslice(Type*, []any, int) []any 2783 fn := syslook("growslice") 2784 fn = substArgTypes(fn, s.Type.Elem(), s.Type.Elem()) 2785 2786 // s = growslice(T, s, n) 2787 nif.Nbody.Set1(nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type.Elem()), s, nn))) 2788 l = append(l, nif) 2789 2790 // s = s[:n] 2791 nt := nod(OSLICE, s, nil) 2792 nt.SetSliceBounds(nil, nn, nil) 2793 nt.Etype = 1 2794 l = append(l, nod(OAS, s, nt)) 2795 2796 if haspointers(l1.Type.Elem()) { 2797 // copy(s[len(l1):], l2) 2798 nptr1 := nod(OSLICE, s, nil) 2799 nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil) 2800 nptr1.Etype = 1 2801 nptr2 := l2 2802 fn := syslook("typedslicecopy") 2803 fn = substArgTypes(fn, l1.Type, l2.Type) 2804 var ln Nodes 2805 ln.Set(l) 2806 nt := mkcall1(fn, Types[TINT], &ln, typename(l1.Type.Elem()), nptr1, nptr2) 2807 l = append(ln.Slice(), nt) 2808 } else if instrumenting && !compiling_runtime { 2809 // rely on runtime to instrument copy. 2810 // copy(s[len(l1):], l2) 2811 nptr1 := nod(OSLICE, s, nil) 2812 nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil) 2813 nptr1.Etype = 1 2814 nptr2 := l2 2815 var fn *Node 2816 if l2.Type.IsString() { 2817 fn = syslook("slicestringcopy") 2818 } else { 2819 fn = syslook("slicecopy") 2820 } 2821 fn = substArgTypes(fn, l1.Type, l2.Type) 2822 var ln Nodes 2823 ln.Set(l) 2824 nt := mkcall1(fn, Types[TINT], &ln, nptr1, nptr2, nodintconst(s.Type.Elem().Width)) 2825 l = append(ln.Slice(), nt) 2826 } else { 2827 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) 2828 nptr1 := nod(OINDEX, s, nod(OLEN, l1, nil)) 2829 nptr1.Bounded = true 2830 2831 nptr1 = nod(OADDR, nptr1, nil) 2832 2833 nptr2 := nod(OSPTR, l2, nil) 2834 2835 fn := syslook("memmove") 2836 fn = substArgTypes(fn, s.Type.Elem(), s.Type.Elem()) 2837 2838 var ln Nodes 2839 ln.Set(l) 2840 nwid := cheapexpr(conv(nod(OLEN, l2, nil), Types[TUINTPTR]), &ln) 2841 2842 nwid = nod(OMUL, nwid, nodintconst(s.Type.Elem().Width)) 2843 nt := mkcall1(fn, nil, &ln, nptr1, nptr2, nwid) 2844 l = append(ln.Slice(), nt) 2845 } 2846 2847 typecheckslice(l, Etop) 2848 walkstmtlist(l) 2849 init.Append(l...) 2850 return s 2851 } 2852 2853 // Rewrite append(src, x, y, z) so that any side effects in 2854 // x, y, z (including runtime panics) are evaluated in 2855 // initialization statements before the append. 2856 // For normal code generation, stop there and leave the 2857 // rest to cgen_append. 2858 // 2859 // For race detector, expand append(src, a [, b]* ) to 2860 // 2861 // init { 2862 // s := src 2863 // const argc = len(args) - 1 2864 // if cap(s) - len(s) < argc { 2865 // s = growslice(s, len(s)+argc) 2866 // } 2867 // n := len(s) 2868 // s = s[:n+argc] 2869 // s[n] = a 2870 // s[n+1] = b 2871 // ... 2872 // } 2873 // s 2874 func walkappend(n *Node, init *Nodes, dst *Node) *Node { 2875 if !samesafeexpr(dst, n.List.First()) { 2876 n.List.SetIndex(0, safeexpr(n.List.Index(0), init)) 2877 n.List.SetIndex(0, walkexpr(n.List.Index(0), init)) 2878 } 2879 walkexprlistsafe(n.List.Slice()[1:], init) 2880 2881 // walkexprlistsafe will leave OINDEX (s[n]) alone if both s 2882 // and n are name or literal, but those may index the slice we're 2883 // modifying here. Fix explicitly. 2884 // Using cheapexpr also makes sure that the evaluation 2885 // of all arguments (and especially any panics) happen 2886 // before we begin to modify the slice in a visible way. 2887 ls := n.List.Slice()[1:] 2888 for i, n := range ls { 2889 ls[i] = cheapexpr(n, init) 2890 } 2891 2892 nsrc := n.List.First() 2893 2894 argc := n.List.Len() - 1 2895 if argc < 1 { 2896 return nsrc 2897 } 2898 2899 // General case, with no function calls left as arguments. 2900 // Leave for gen, except that instrumentation requires old form. 2901 if !instrumenting || compiling_runtime { 2902 return n 2903 } 2904 2905 var l []*Node 2906 2907 ns := temp(nsrc.Type) 2908 l = append(l, nod(OAS, ns, nsrc)) // s = src 2909 2910 na := nodintconst(int64(argc)) // const argc 2911 nx := nod(OIF, nil, nil) // if cap(s) - len(s) < argc 2912 nx.Left = nod(OLT, nod(OSUB, nod(OCAP, ns, nil), nod(OLEN, ns, nil)), na) 2913 2914 fn := syslook("growslice") // growslice(<type>, old []T, mincap int) (ret []T) 2915 fn = substArgTypes(fn, ns.Type.Elem(), ns.Type.Elem()) 2916 2917 nx.Nbody.Set1(nod(OAS, ns, 2918 mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type.Elem()), ns, 2919 nod(OADD, nod(OLEN, ns, nil), na)))) 2920 2921 l = append(l, nx) 2922 2923 nn := temp(Types[TINT]) 2924 l = append(l, nod(OAS, nn, nod(OLEN, ns, nil))) // n = len(s) 2925 2926 nx = nod(OSLICE, ns, nil) // ...s[:n+argc] 2927 nx.SetSliceBounds(nil, nod(OADD, nn, na), nil) 2928 nx.Etype = 1 2929 l = append(l, nod(OAS, ns, nx)) // s = s[:n+argc] 2930 2931 ls = n.List.Slice()[1:] 2932 for i, n := range ls { 2933 nx = nod(OINDEX, ns, nn) // s[n] ... 2934 nx.Bounded = true 2935 l = append(l, nod(OAS, nx, n)) // s[n] = arg 2936 if i+1 < len(ls) { 2937 l = append(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))) // n = n + 1 2938 } 2939 } 2940 2941 typecheckslice(l, Etop) 2942 walkstmtlist(l) 2943 init.Append(l...) 2944 return ns 2945 } 2946 2947 // Lower copy(a, b) to a memmove call or a runtime call. 2948 // 2949 // init { 2950 // n := len(a) 2951 // if n > len(b) { n = len(b) } 2952 // memmove(a.ptr, b.ptr, n*sizeof(elem(a))) 2953 // } 2954 // n; 2955 // 2956 // Also works if b is a string. 2957 // 2958 func copyany(n *Node, init *Nodes, runtimecall bool) *Node { 2959 if haspointers(n.Left.Type.Elem()) { 2960 fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type) 2961 return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), n.Left, n.Right) 2962 } 2963 2964 if runtimecall { 2965 var fn *Node 2966 if n.Right.Type.IsString() { 2967 fn = syslook("slicestringcopy") 2968 } else { 2969 fn = syslook("slicecopy") 2970 } 2971 fn = substArgTypes(fn, n.Left.Type, n.Right.Type) 2972 return mkcall1(fn, n.Type, init, n.Left, n.Right, nodintconst(n.Left.Type.Elem().Width)) 2973 } 2974 2975 n.Left = walkexpr(n.Left, init) 2976 n.Right = walkexpr(n.Right, init) 2977 nl := temp(n.Left.Type) 2978 nr := temp(n.Right.Type) 2979 var l []*Node 2980 l = append(l, nod(OAS, nl, n.Left)) 2981 l = append(l, nod(OAS, nr, n.Right)) 2982 2983 nfrm := nod(OSPTR, nr, nil) 2984 nto := nod(OSPTR, nl, nil) 2985 2986 nlen := temp(Types[TINT]) 2987 2988 // n = len(to) 2989 l = append(l, nod(OAS, nlen, nod(OLEN, nl, nil))) 2990 2991 // if n > len(frm) { n = len(frm) } 2992 nif := nod(OIF, nil, nil) 2993 2994 nif.Left = nod(OGT, nlen, nod(OLEN, nr, nil)) 2995 nif.Nbody.Append(nod(OAS, nlen, nod(OLEN, nr, nil))) 2996 l = append(l, nif) 2997 2998 // Call memmove. 2999 fn := syslook("memmove") 3000 3001 fn = substArgTypes(fn, nl.Type.Elem(), nl.Type.Elem()) 3002 nwid := temp(Types[TUINTPTR]) 3003 l = append(l, nod(OAS, nwid, conv(nlen, Types[TUINTPTR]))) 3004 nwid = nod(OMUL, nwid, nodintconst(nl.Type.Elem().Width)) 3005 l = append(l, mkcall1(fn, nil, init, nto, nfrm, nwid)) 3006 3007 typecheckslice(l, Etop) 3008 walkstmtlist(l) 3009 init.Append(l...) 3010 return nlen 3011 } 3012 3013 func eqfor(t *Type, needsize *int) *Node { 3014 // Should only arrive here with large memory or 3015 // a struct/array containing a non-memory field/element. 3016 // Small memory is handled inline, and single non-memory 3017 // is handled during type check (OCMPSTR etc). 3018 switch a, _ := algtype1(t); a { 3019 case AMEM: 3020 n := syslook("memequal") 3021 n = substArgTypes(n, t, t) 3022 *needsize = 1 3023 return n 3024 case ASPECIAL: 3025 sym := typesymprefix(".eq", t) 3026 n := newname(sym) 3027 n.Class = PFUNC 3028 ntype := nod(OTFUNC, nil, nil) 3029 ntype.List.Append(nod(ODCLFIELD, nil, typenod(ptrto(t)))) 3030 ntype.List.Append(nod(ODCLFIELD, nil, typenod(ptrto(t)))) 3031 ntype.Rlist.Append(nod(ODCLFIELD, nil, typenod(Types[TBOOL]))) 3032 ntype = typecheck(ntype, Etype) 3033 n.Type = ntype.Type 3034 *needsize = 0 3035 return n 3036 } 3037 Fatalf("eqfor %v", t) 3038 return nil 3039 } 3040 3041 // The result of walkcompare MUST be assigned back to n, e.g. 3042 // n.Left = walkcompare(n.Left, init) 3043 func walkcompare(n *Node, init *Nodes) *Node { 3044 // Given interface value l and concrete value r, rewrite 3045 // l == r 3046 // into types-equal && data-equal. 3047 // This is efficient, avoids allocations, and avoids runtime calls. 3048 var l, r *Node 3049 if n.Left.Type.IsInterface() && !n.Right.Type.IsInterface() { 3050 l = n.Left 3051 r = n.Right 3052 } else if !n.Left.Type.IsInterface() && n.Right.Type.IsInterface() { 3053 l = n.Right 3054 r = n.Left 3055 } 3056 3057 if l != nil { 3058 // Handle both == and !=. 3059 eq := n.Op 3060 var andor Op 3061 if eq == OEQ { 3062 andor = OANDAND 3063 } else { 3064 andor = OOROR 3065 } 3066 // Check for types equal. 3067 // For empty interface, this is: 3068 // l.tab == type(r) 3069 // For non-empty interface, this is: 3070 // l.tab != nil && l.tab._type == type(r) 3071 var eqtype *Node 3072 tab := nod(OITAB, l, nil) 3073 rtyp := typename(r.Type) 3074 if l.Type.IsEmptyInterface() { 3075 tab.Type = ptrto(Types[TUINT8]) 3076 tab.Typecheck = 1 3077 eqtype = nod(eq, tab, rtyp) 3078 } else { 3079 nonnil := nod(brcom(eq), nodnil(), tab) 3080 match := nod(eq, itabType(tab), rtyp) 3081 eqtype = nod(andor, nonnil, match) 3082 } 3083 // Check for data equal. 3084 eqdata := nod(eq, ifaceData(l, r.Type), r) 3085 // Put it all together. 3086 expr := nod(andor, eqtype, eqdata) 3087 n = finishcompare(n, expr, init) 3088 return n 3089 } 3090 3091 // Must be comparison of array or struct. 3092 // Otherwise back end handles it. 3093 // While we're here, decide whether to 3094 // inline or call an eq alg. 3095 t := n.Left.Type 3096 var inline bool 3097 switch t.Etype { 3098 default: 3099 return n 3100 case TARRAY: 3101 inline = t.NumElem() <= 1 || (t.NumElem() <= 4 && issimple[t.Elem().Etype]) 3102 case TSTRUCT: 3103 inline = t.NumFields() <= 4 3104 } 3105 3106 cmpl := n.Left 3107 for cmpl != nil && cmpl.Op == OCONVNOP { 3108 cmpl = cmpl.Left 3109 } 3110 cmpr := n.Right 3111 for cmpr != nil && cmpr.Op == OCONVNOP { 3112 cmpr = cmpr.Left 3113 } 3114 3115 // Chose not to inline. Call equality function directly. 3116 if !inline { 3117 if isvaluelit(cmpl) { 3118 var_ := temp(cmpl.Type) 3119 anylit(cmpl, var_, init) 3120 cmpl = var_ 3121 } 3122 if isvaluelit(cmpr) { 3123 var_ := temp(cmpr.Type) 3124 anylit(cmpr, var_, init) 3125 cmpr = var_ 3126 } 3127 if !islvalue(cmpl) || !islvalue(cmpr) { 3128 Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr) 3129 } 3130 3131 // eq algs take pointers 3132 pl := temp(ptrto(t)) 3133 al := nod(OAS, pl, nod(OADDR, cmpl, nil)) 3134 al.Right.Etype = 1 // addr does not escape 3135 al = typecheck(al, Etop) 3136 init.Append(al) 3137 3138 pr := temp(ptrto(t)) 3139 ar := nod(OAS, pr, nod(OADDR, cmpr, nil)) 3140 ar.Right.Etype = 1 // addr does not escape 3141 ar = typecheck(ar, Etop) 3142 init.Append(ar) 3143 3144 var needsize int 3145 call := nod(OCALL, eqfor(t, &needsize), nil) 3146 call.List.Append(pl) 3147 call.List.Append(pr) 3148 if needsize != 0 { 3149 call.List.Append(nodintconst(t.Width)) 3150 } 3151 res := call 3152 if n.Op != OEQ { 3153 res = nod(ONOT, res, nil) 3154 } 3155 n = finishcompare(n, res, init) 3156 return n 3157 } 3158 3159 // inline: build boolean expression comparing element by element 3160 andor := OANDAND 3161 if n.Op == ONE { 3162 andor = OOROR 3163 } 3164 var expr *Node 3165 compare := func(el, er *Node) { 3166 a := nod(n.Op, el, er) 3167 if expr == nil { 3168 expr = a 3169 } else { 3170 expr = nod(andor, expr, a) 3171 } 3172 } 3173 cmpl = safeexpr(cmpl, init) 3174 cmpr = safeexpr(cmpr, init) 3175 if t.IsStruct() { 3176 for _, f := range t.Fields().Slice() { 3177 sym := f.Sym 3178 if isblanksym(sym) { 3179 continue 3180 } 3181 compare( 3182 nodSym(OXDOT, cmpl, sym), 3183 nodSym(OXDOT, cmpr, sym), 3184 ) 3185 } 3186 } else { 3187 for i := 0; int64(i) < t.NumElem(); i++ { 3188 compare( 3189 nod(OINDEX, cmpl, nodintconst(int64(i))), 3190 nod(OINDEX, cmpr, nodintconst(int64(i))), 3191 ) 3192 } 3193 } 3194 if expr == nil { 3195 expr = nodbool(n.Op == OEQ) 3196 } 3197 n = finishcompare(n, expr, init) 3198 return n 3199 } 3200 3201 // The result of finishcompare MUST be assigned back to n, e.g. 3202 // n.Left = finishcompare(n.Left, x, r, init) 3203 func finishcompare(n, r *Node, init *Nodes) *Node { 3204 // Use nn here to avoid passing r to typecheck. 3205 nn := r 3206 nn = typecheck(nn, Erv) 3207 nn = walkexpr(nn, init) 3208 r = nn 3209 if r.Type != n.Type { 3210 r = nod(OCONVNOP, r, nil) 3211 r.Type = n.Type 3212 r.Typecheck = 1 3213 nn = r 3214 } 3215 return nn 3216 } 3217 3218 // isIntOrdering reports whether n is a <, ≤, >, or ≥ ordering between integers. 3219 func (n *Node) isIntOrdering() bool { 3220 switch n.Op { 3221 case OLE, OLT, OGE, OGT: 3222 default: 3223 return false 3224 } 3225 return n.Left.Type.IsInteger() && n.Right.Type.IsInteger() 3226 } 3227 3228 // walkinrange optimizes integer-in-range checks, such as 4 <= x && x < 10. 3229 // n must be an OANDAND or OOROR node. 3230 // The result of walkinrange MUST be assigned back to n, e.g. 3231 // n.Left = walkinrange(n.Left) 3232 func walkinrange(n *Node, init *Nodes) *Node { 3233 // We are looking for something equivalent to a opl b OP b opr c, where: 3234 // * a, b, and c have integer type 3235 // * b is side-effect-free 3236 // * opl and opr are each < or ≤ 3237 // * OP is && 3238 l := n.Left 3239 r := n.Right 3240 if !l.isIntOrdering() || !r.isIntOrdering() { 3241 return n 3242 } 3243 3244 // Find b, if it exists, and rename appropriately. 3245 // Input is: l.Left l.Op l.Right ANDAND/OROR r.Left r.Op r.Right 3246 // Output is: a opl b(==x) ANDAND/OROR b(==x) opr c 3247 a, opl, b := l.Left, l.Op, l.Right 3248 x, opr, c := r.Left, r.Op, r.Right 3249 for i := 0; ; i++ { 3250 if samesafeexpr(b, x) { 3251 break 3252 } 3253 if i == 3 { 3254 // Tried all permutations and couldn't find an appropriate b == x. 3255 return n 3256 } 3257 if i&1 == 0 { 3258 a, opl, b = b, brrev(opl), a 3259 } else { 3260 x, opr, c = c, brrev(opr), x 3261 } 3262 } 3263 3264 // If n.Op is ||, apply de Morgan. 3265 // Negate the internal ops now; we'll negate the top level op at the end. 3266 // Henceforth assume &&. 3267 negateResult := n.Op == OOROR 3268 if negateResult { 3269 opl = brcom(opl) 3270 opr = brcom(opr) 3271 } 3272 3273 cmpdir := func(o Op) int { 3274 switch o { 3275 case OLE, OLT: 3276 return -1 3277 case OGE, OGT: 3278 return +1 3279 } 3280 Fatalf("walkinrange cmpdir %v", o) 3281 return 0 3282 } 3283 if cmpdir(opl) != cmpdir(opr) { 3284 // Not a range check; something like b < a && b < c. 3285 return n 3286 } 3287 3288 switch opl { 3289 case OGE, OGT: 3290 // We have something like a > b && b ≥ c. 3291 // Switch and reverse ops and rename constants, 3292 // to make it look like a ≤ b && b < c. 3293 a, c = c, a 3294 opl, opr = brrev(opr), brrev(opl) 3295 } 3296 3297 // We must ensure that c-a is non-negative. 3298 // For now, require a and c to be constants. 3299 // In the future, we could also support a == 0 and c == len/cap(...). 3300 // Unfortunately, by this point, most len/cap expressions have been 3301 // stored into temporary variables. 3302 if !Isconst(a, CTINT) || !Isconst(c, CTINT) { 3303 return n 3304 } 3305 3306 if opl == OLT { 3307 // We have a < b && ... 3308 // We need a ≤ b && ... to safely use unsigned comparison tricks. 3309 // If a is not the maximum constant for b's type, 3310 // we can increment a and switch to ≤. 3311 if a.Int64() >= maxintval[b.Type.Etype].Int64() { 3312 return n 3313 } 3314 a = nodintconst(a.Int64() + 1) 3315 opl = OLE 3316 } 3317 3318 bound := c.Int64() - a.Int64() 3319 if bound < 0 { 3320 // Bad news. Something like 5 <= x && x < 3. 3321 // Rare in practice, and we still need to generate side-effects, 3322 // so just leave it alone. 3323 return n 3324 } 3325 3326 // We have a ≤ b && b < c (or a ≤ b && b ≤ c). 3327 // This is equivalent to (a-a) ≤ (b-a) && (b-a) < (c-a), 3328 // which is equivalent to 0 ≤ (b-a) && (b-a) < (c-a), 3329 // which is equivalent to uint(b-a) < uint(c-a). 3330 ut := b.Type.toUnsigned() 3331 lhs := conv(nod(OSUB, b, a), ut) 3332 rhs := nodintconst(bound) 3333 if negateResult { 3334 // Negate top level. 3335 opr = brcom(opr) 3336 } 3337 cmp := nod(opr, lhs, rhs) 3338 cmp.Pos = n.Pos 3339 cmp = addinit(cmp, l.Ninit.Slice()) 3340 cmp = addinit(cmp, r.Ninit.Slice()) 3341 // Typecheck the AST rooted at cmp... 3342 cmp = typecheck(cmp, Erv) 3343 // ...but then reset cmp's type to match n's type. 3344 cmp.Type = n.Type 3345 cmp = walkexpr(cmp, init) 3346 return cmp 3347 } 3348 3349 // walkdiv rewrites division by a constant as less expensive 3350 // operations. 3351 // The result of walkdiv MUST be assigned back to n, e.g. 3352 // n.Left = walkdiv(n.Left, init) 3353 func walkdiv(n *Node, init *Nodes) *Node { 3354 // if >= 0, nr is 1<<pow // 1 if nr is negative. 3355 3356 if n.Right.Op != OLITERAL { 3357 return n 3358 } 3359 3360 // nr is a constant. 3361 nl := cheapexpr(n.Left, init) 3362 3363 nr := n.Right 3364 3365 // special cases of mod/div 3366 // by a constant 3367 w := int(nl.Type.Width * 8) 3368 3369 s := 0 // 1 if nr is negative. 3370 pow := powtwo(nr) // if >= 0, nr is 1<<pow 3371 if pow >= 1000 { 3372 // negative power of 2 3373 s = 1 3374 3375 pow -= 1000 3376 } 3377 3378 if pow+1 >= w { 3379 // divisor too large. 3380 return n 3381 } 3382 3383 if pow < 0 { 3384 // try to do division by multiply by (2^w)/d 3385 // see hacker's delight chapter 10 3386 // TODO: support 64-bit magic multiply here. 3387 var m Magic 3388 m.W = w 3389 3390 if nl.Type.IsSigned() { 3391 m.Sd = nr.Int64() 3392 smagic(&m) 3393 } else { 3394 m.Ud = uint64(nr.Int64()) 3395 umagic(&m) 3396 } 3397 3398 if m.Bad != 0 { 3399 return n 3400 } 3401 3402 // We have a quick division method so use it 3403 // for modulo too. 3404 if n.Op == OMOD { 3405 // rewrite as A%B = A - (A/B*B). 3406 n1 := nod(ODIV, nl, nr) 3407 3408 n2 := nod(OMUL, n1, nr) 3409 n = nod(OSUB, nl, n2) 3410 goto ret 3411 } 3412 3413 switch simtype[nl.Type.Etype] { 3414 default: 3415 return n 3416 3417 // n1 = nl * magic >> w (HMUL) 3418 case TUINT8, TUINT16, TUINT32: 3419 var nc Node 3420 3421 nodconst(&nc, nl.Type, int64(m.Um)) 3422 n1 := nod(OHMUL, nl, &nc) 3423 n1 = typecheck(n1, Erv) 3424 if m.Ua != 0 { 3425 // Select a Go type with (at least) twice the width. 3426 var twide *Type 3427 switch simtype[nl.Type.Etype] { 3428 default: 3429 return n 3430 3431 case TUINT8, TUINT16: 3432 twide = Types[TUINT32] 3433 3434 case TUINT32: 3435 twide = Types[TUINT64] 3436 3437 case TINT8, TINT16: 3438 twide = Types[TINT32] 3439 3440 case TINT32: 3441 twide = Types[TINT64] 3442 } 3443 3444 // add numerator (might overflow). 3445 // n2 = (n1 + nl) 3446 n2 := nod(OADD, conv(n1, twide), conv(nl, twide)) 3447 3448 // shift by m.s 3449 var nc Node 3450 3451 nodconst(&nc, Types[TUINT], int64(m.S)) 3452 n = conv(nod(ORSH, n2, &nc), nl.Type) 3453 } else { 3454 // n = n1 >> m.s 3455 var nc Node 3456 3457 nodconst(&nc, Types[TUINT], int64(m.S)) 3458 n = nod(ORSH, n1, &nc) 3459 } 3460 3461 // n1 = nl * magic >> w 3462 case TINT8, TINT16, TINT32: 3463 var nc Node 3464 3465 nodconst(&nc, nl.Type, m.Sm) 3466 n1 := nod(OHMUL, nl, &nc) 3467 n1 = typecheck(n1, Erv) 3468 if m.Sm < 0 { 3469 // add the numerator. 3470 n1 = nod(OADD, n1, nl) 3471 } 3472 3473 // shift by m.s 3474 var ns Node 3475 3476 nodconst(&ns, Types[TUINT], int64(m.S)) 3477 n2 := conv(nod(ORSH, n1, &ns), nl.Type) 3478 3479 // add 1 iff n1 is negative. 3480 var nneg Node 3481 3482 nodconst(&nneg, Types[TUINT], int64(w)-1) 3483 n3 := nod(ORSH, nl, &nneg) // n4 = -1 iff n1 is negative. 3484 n = nod(OSUB, n2, n3) 3485 3486 // apply sign. 3487 if m.Sd < 0 { 3488 n = nod(OMINUS, n, nil) 3489 } 3490 } 3491 3492 goto ret 3493 } 3494 3495 switch pow { 3496 case 0: 3497 if n.Op == OMOD { 3498 // nl % 1 is zero. 3499 nodconst(n, n.Type, 0) 3500 } else if s != 0 { 3501 // divide by -1 3502 n.Op = OMINUS 3503 3504 n.Right = nil 3505 } else { 3506 // divide by 1 3507 n = nl 3508 } 3509 3510 default: 3511 if n.Type.IsSigned() { 3512 if n.Op == OMOD { 3513 // signed modulo 2^pow is like ANDing 3514 // with the last pow bits, but if nl < 0, 3515 // nl & (2^pow-1) is (nl+1)%2^pow - 1. 3516 var nc Node 3517 3518 nodconst(&nc, Types[simtype[TUINT]], int64(w)-1) 3519 n1 := nod(ORSH, nl, &nc) // n1 = -1 iff nl < 0. 3520 if pow == 1 { 3521 n1 = typecheck(n1, Erv) 3522 n1 = cheapexpr(n1, init) 3523 3524 // n = (nl+ε)&1 -ε where ε=1 iff nl<0. 3525 n2 := nod(OSUB, nl, n1) 3526 3527 var nc Node 3528 nodconst(&nc, nl.Type, 1) 3529 n3 := nod(OAND, n2, &nc) 3530 n = nod(OADD, n3, n1) 3531 } else { 3532 // n = (nl+ε)&(nr-1) - ε where ε=2^pow-1 iff nl<0. 3533 var nc Node 3534 3535 nodconst(&nc, nl.Type, (1<<uint(pow))-1) 3536 n2 := nod(OAND, n1, &nc) // n2 = 2^pow-1 iff nl<0. 3537 n2 = typecheck(n2, Erv) 3538 n2 = cheapexpr(n2, init) 3539 3540 n3 := nod(OADD, nl, n2) 3541 n4 := nod(OAND, n3, &nc) 3542 n = nod(OSUB, n4, n2) 3543 } 3544 3545 break 3546 } else { 3547 // arithmetic right shift does not give the correct rounding. 3548 // if nl >= 0, nl >> n == nl / nr 3549 // if nl < 0, we want to add 2^n-1 first. 3550 var nc Node 3551 3552 nodconst(&nc, Types[simtype[TUINT]], int64(w)-1) 3553 n1 := nod(ORSH, nl, &nc) // n1 = -1 iff nl < 0. 3554 if pow == 1 { 3555 // nl+1 is nl-(-1) 3556 n.Left = nod(OSUB, nl, n1) 3557 } else { 3558 // Do a logical right right on -1 to keep pow bits. 3559 var nc Node 3560 3561 nodconst(&nc, Types[simtype[TUINT]], int64(w)-int64(pow)) 3562 n2 := nod(ORSH, conv(n1, nl.Type.toUnsigned()), &nc) 3563 n.Left = nod(OADD, nl, conv(n2, nl.Type)) 3564 } 3565 3566 // n = (nl + 2^pow-1) >> pow 3567 n.Op = ORSH 3568 3569 var n2 Node 3570 nodconst(&n2, Types[simtype[TUINT]], int64(pow)) 3571 n.Right = &n2 3572 n.Typecheck = 0 3573 } 3574 3575 if s != 0 { 3576 n = nod(OMINUS, n, nil) 3577 } 3578 break 3579 } 3580 3581 var nc Node 3582 if n.Op == OMOD { 3583 // n = nl & (nr-1) 3584 n.Op = OAND 3585 3586 nodconst(&nc, nl.Type, nr.Int64()-1) 3587 } else { 3588 // n = nl >> pow 3589 n.Op = ORSH 3590 3591 nodconst(&nc, Types[simtype[TUINT]], int64(pow)) 3592 } 3593 3594 n.Typecheck = 0 3595 n.Right = &nc 3596 } 3597 3598 goto ret 3599 3600 ret: 3601 n = typecheck(n, Erv) 3602 n = walkexpr(n, init) 3603 return n 3604 } 3605 3606 // return 1 if integer n must be in range [0, max), 0 otherwise 3607 func bounded(n *Node, max int64) bool { 3608 if n.Type == nil || !n.Type.IsInteger() { 3609 return false 3610 } 3611 3612 sign := n.Type.IsSigned() 3613 bits := int32(8 * n.Type.Width) 3614 3615 if smallintconst(n) { 3616 v := n.Int64() 3617 return 0 <= v && v < max 3618 } 3619 3620 switch n.Op { 3621 case OAND: 3622 v := int64(-1) 3623 if smallintconst(n.Left) { 3624 v = n.Left.Int64() 3625 } else if smallintconst(n.Right) { 3626 v = n.Right.Int64() 3627 } 3628 3629 if 0 <= v && v < max { 3630 return true 3631 } 3632 3633 case OMOD: 3634 if !sign && smallintconst(n.Right) { 3635 v := n.Right.Int64() 3636 if 0 <= v && v <= max { 3637 return true 3638 } 3639 } 3640 3641 case ODIV: 3642 if !sign && smallintconst(n.Right) { 3643 v := n.Right.Int64() 3644 for bits > 0 && v >= 2 { 3645 bits-- 3646 v >>= 1 3647 } 3648 } 3649 3650 case ORSH: 3651 if !sign && smallintconst(n.Right) { 3652 v := n.Right.Int64() 3653 if v > int64(bits) { 3654 return true 3655 } 3656 bits -= int32(v) 3657 } 3658 } 3659 3660 if !sign && bits <= 62 && 1<<uint(bits) <= max { 3661 return true 3662 } 3663 3664 return false 3665 } 3666 3667 // usemethod check interface method calls for uses of reflect.Type.Method. 3668 func usemethod(n *Node) { 3669 t := n.Left.Type 3670 3671 // Looking for either of: 3672 // Method(int) reflect.Method 3673 // MethodByName(string) (reflect.Method, bool) 3674 // 3675 // TODO(crawshaw): improve precision of match by working out 3676 // how to check the method name. 3677 if n := t.Params().NumFields(); n != 1 { 3678 return 3679 } 3680 if n := t.Results().NumFields(); n != 1 && n != 2 { 3681 return 3682 } 3683 p0 := t.Params().Field(0) 3684 res0 := t.Results().Field(0) 3685 var res1 *Field 3686 if t.Results().NumFields() == 2 { 3687 res1 = t.Results().Field(1) 3688 } 3689 3690 if res1 == nil { 3691 if p0.Type.Etype != TINT { 3692 return 3693 } 3694 } else { 3695 if !p0.Type.IsString() { 3696 return 3697 } 3698 if !res1.Type.IsBoolean() { 3699 return 3700 } 3701 } 3702 if res0.Type.String() != "reflect.Method" { 3703 return 3704 } 3705 3706 Curfn.Func.ReflectMethod = true 3707 } 3708 3709 func usefield(n *Node) { 3710 if obj.Fieldtrack_enabled == 0 { 3711 return 3712 } 3713 3714 switch n.Op { 3715 default: 3716 Fatalf("usefield %v", n.Op) 3717 3718 case ODOT, ODOTPTR: 3719 break 3720 } 3721 if n.Sym == nil { 3722 // No field name. This DOTPTR was built by the compiler for access 3723 // to runtime data structures. Ignore. 3724 return 3725 } 3726 3727 t := n.Left.Type 3728 if t.IsPtr() { 3729 t = t.Elem() 3730 } 3731 field := dotField[typeSym{t.Orig, n.Sym}] 3732 if field == nil { 3733 Fatalf("usefield %v %v without paramfld", n.Left.Type, n.Sym) 3734 } 3735 if !strings.Contains(field.Note, "go:\"track\"") { 3736 return 3737 } 3738 3739 outer := n.Left.Type 3740 if outer.IsPtr() { 3741 outer = outer.Elem() 3742 } 3743 if outer.Sym == nil { 3744 yyerror("tracked field must be in named struct type") 3745 } 3746 if !exportname(field.Sym.Name) { 3747 yyerror("tracked field must be exported (upper case)") 3748 } 3749 3750 sym := tracksym(outer, field) 3751 if Curfn.Func.FieldTrack == nil { 3752 Curfn.Func.FieldTrack = make(map[*Sym]struct{}) 3753 } 3754 Curfn.Func.FieldTrack[sym] = struct{}{} 3755 } 3756 3757 func candiscardlist(l Nodes) bool { 3758 for _, n := range l.Slice() { 3759 if !candiscard(n) { 3760 return false 3761 } 3762 } 3763 return true 3764 } 3765 3766 func candiscard(n *Node) bool { 3767 if n == nil { 3768 return true 3769 } 3770 3771 switch n.Op { 3772 default: 3773 return false 3774 3775 // Discardable as long as the subpieces are. 3776 case ONAME, 3777 ONONAME, 3778 OTYPE, 3779 OPACK, 3780 OLITERAL, 3781 OADD, 3782 OSUB, 3783 OOR, 3784 OXOR, 3785 OADDSTR, 3786 OADDR, 3787 OANDAND, 3788 OARRAYBYTESTR, 3789 OARRAYRUNESTR, 3790 OSTRARRAYBYTE, 3791 OSTRARRAYRUNE, 3792 OCAP, 3793 OCMPIFACE, 3794 OCMPSTR, 3795 OCOMPLIT, 3796 OMAPLIT, 3797 OSTRUCTLIT, 3798 OARRAYLIT, 3799 OSLICELIT, 3800 OPTRLIT, 3801 OCONV, 3802 OCONVIFACE, 3803 OCONVNOP, 3804 ODOT, 3805 OEQ, 3806 ONE, 3807 OLT, 3808 OLE, 3809 OGT, 3810 OGE, 3811 OKEY, 3812 OSTRUCTKEY, 3813 OLEN, 3814 OMUL, 3815 OLSH, 3816 ORSH, 3817 OAND, 3818 OANDNOT, 3819 ONEW, 3820 ONOT, 3821 OCOM, 3822 OPLUS, 3823 OMINUS, 3824 OOROR, 3825 OPAREN, 3826 ORUNESTR, 3827 OREAL, 3828 OIMAG, 3829 OCOMPLEX: 3830 break 3831 3832 // Discardable as long as we know it's not division by zero. 3833 case ODIV, OMOD: 3834 if Isconst(n.Right, CTINT) && n.Right.Val().U.(*Mpint).CmpInt64(0) != 0 { 3835 break 3836 } 3837 if Isconst(n.Right, CTFLT) && n.Right.Val().U.(*Mpflt).CmpFloat64(0) != 0 { 3838 break 3839 } 3840 return false 3841 3842 // Discardable as long as we know it won't fail because of a bad size. 3843 case OMAKECHAN, OMAKEMAP: 3844 if Isconst(n.Left, CTINT) && n.Left.Val().U.(*Mpint).CmpInt64(0) == 0 { 3845 break 3846 } 3847 return false 3848 3849 // Difficult to tell what sizes are okay. 3850 case OMAKESLICE: 3851 return false 3852 } 3853 3854 if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) { 3855 return false 3856 } 3857 3858 return true 3859 } 3860 3861 // rewrite 3862 // print(x, y, z) 3863 // into 3864 // func(a1, a2, a3) { 3865 // print(a1, a2, a3) 3866 // }(x, y, z) 3867 // and same for println. 3868 3869 var walkprintfunc_prgen int 3870 3871 // The result of walkprintfunc MUST be assigned back to n, e.g. 3872 // n.Left = walkprintfunc(n.Left, init) 3873 func walkprintfunc(n *Node, init *Nodes) *Node { 3874 if n.Ninit.Len() != 0 { 3875 walkstmtlist(n.Ninit.Slice()) 3876 init.AppendNodes(&n.Ninit) 3877 } 3878 3879 t := nod(OTFUNC, nil, nil) 3880 num := 0 3881 var printargs []*Node 3882 var a *Node 3883 var buf string 3884 for _, n1 := range n.List.Slice() { 3885 buf = fmt.Sprintf("a%d", num) 3886 num++ 3887 a = nod(ODCLFIELD, newname(lookup(buf)), typenod(n1.Type)) 3888 t.List.Append(a) 3889 printargs = append(printargs, a.Left) 3890 } 3891 3892 fn := nod(ODCLFUNC, nil, nil) 3893 walkprintfunc_prgen++ 3894 buf = fmt.Sprintf("print·%d", walkprintfunc_prgen) 3895 fn.Func.Nname = newname(lookup(buf)) 3896 fn.Func.Nname.Name.Defn = fn 3897 fn.Func.Nname.Name.Param.Ntype = t 3898 declare(fn.Func.Nname, PFUNC) 3899 3900 oldfn := Curfn 3901 Curfn = nil 3902 funchdr(fn) 3903 3904 a = nod(n.Op, nil, nil) 3905 a.List.Set(printargs) 3906 a = typecheck(a, Etop) 3907 a = walkstmt(a) 3908 3909 fn.Nbody.Set1(a) 3910 3911 funcbody(fn) 3912 3913 fn = typecheck(fn, Etop) 3914 typecheckslice(fn.Nbody.Slice(), Etop) 3915 xtop = append(xtop, fn) 3916 Curfn = oldfn 3917 3918 a = nod(OCALL, nil, nil) 3919 a.Left = fn.Func.Nname 3920 a.List.Set(n.List.Slice()) 3921 a = typecheck(a, Etop) 3922 a = walkexpr(a, init) 3923 return a 3924 }