github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/compile/internal/gc/order.go (about) 1 // Copyright 2012 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/src" 9 "fmt" 10 ) 11 12 // Rewrite tree to use separate statements to enforce 13 // order of evaluation. Makes walk easier, because it 14 // can (after this runs) reorder at will within an expression. 15 // 16 // Rewrite x op= y into x = x op y. 17 // 18 // Introduce temporaries as needed by runtime routines. 19 // For example, the map runtime routines take the map key 20 // by reference, so make sure all map keys are addressable 21 // by copying them to temporaries as needed. 22 // The same is true for channel operations. 23 // 24 // Arrange that map index expressions only appear in direct 25 // assignments x = m[k] or m[k] = x, never in larger expressions. 26 // 27 // Arrange that receive expressions only appear in direct assignments 28 // x = <-c or as standalone statements <-c, never in larger expressions. 29 30 // TODO(rsc): The temporary introduction during multiple assignments 31 // should be moved into this file, so that the temporaries can be cleaned 32 // and so that conversions implicit in the OAS2FUNC and OAS2RECV 33 // nodes can be made explicit and then have their temporaries cleaned. 34 35 // TODO(rsc): Goto and multilevel break/continue can jump over 36 // inserted VARKILL annotations. Work out a way to handle these. 37 // The current implementation is safe, in that it will execute correctly. 38 // But it won't reuse temporaries as aggressively as it might, and 39 // it can result in unnecessary zeroing of those variables in the function 40 // prologue. 41 42 // Order holds state during the ordering process. 43 type Order struct { 44 out []*Node // list of generated statements 45 temp []*Node // stack of temporary variables 46 } 47 48 // Order rewrites fn->nbody to apply the ordering constraints 49 // described in the comment at the top of the file. 50 func order(fn *Node) { 51 if Debug['W'] > 1 { 52 s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym) 53 dumplist(s, fn.Nbody) 54 } 55 56 orderblockNodes(&fn.Nbody) 57 } 58 59 // Ordertemp allocates a new temporary with the given type, 60 // pushes it onto the temp stack, and returns it. 61 // If clear is true, ordertemp emits code to zero the temporary. 62 func ordertemp(t *Type, order *Order, clear bool) *Node { 63 var_ := temp(t) 64 if clear { 65 a := nod(OAS, var_, nil) 66 a = typecheck(a, Etop) 67 order.out = append(order.out, a) 68 } 69 70 order.temp = append(order.temp, var_) 71 return var_ 72 } 73 74 // Ordercopyexpr behaves like ordertemp but also emits 75 // code to initialize the temporary to the value n. 76 // 77 // The clear argument is provided for use when the evaluation 78 // of tmp = n turns into a function call that is passed a pointer 79 // to the temporary as the output space. If the call blocks before 80 // tmp has been written, the garbage collector will still treat the 81 // temporary as live, so we must zero it before entering that call. 82 // Today, this only happens for channel receive operations. 83 // (The other candidate would be map access, but map access 84 // returns a pointer to the result data instead of taking a pointer 85 // to be filled in.) 86 func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node { 87 var_ := ordertemp(t, order, clear != 0) 88 a := nod(OAS, var_, n) 89 a = typecheck(a, Etop) 90 order.out = append(order.out, a) 91 return var_ 92 } 93 94 // Ordercheapexpr returns a cheap version of n. 95 // The definition of cheap is that n is a variable or constant. 96 // If not, ordercheapexpr allocates a new tmp, emits tmp = n, 97 // and then returns tmp. 98 func ordercheapexpr(n *Node, order *Order) *Node { 99 if n == nil { 100 return nil 101 } 102 switch n.Op { 103 case ONAME, OLITERAL: 104 return n 105 case OLEN, OCAP: 106 l := ordercheapexpr(n.Left, order) 107 if l == n.Left { 108 return n 109 } 110 a := *n 111 a.Orig = &a 112 a.Left = l 113 return typecheck(&a, Erv) 114 } 115 116 return ordercopyexpr(n, n.Type, order, 0) 117 } 118 119 // Ordersafeexpr returns a safe version of n. 120 // The definition of safe is that n can appear multiple times 121 // without violating the semantics of the original program, 122 // and that assigning to the safe version has the same effect 123 // as assigning to the original n. 124 // 125 // The intended use is to apply to x when rewriting x += y into x = x + y. 126 func ordersafeexpr(n *Node, order *Order) *Node { 127 switch n.Op { 128 case ONAME, OLITERAL: 129 return n 130 131 case ODOT, OLEN, OCAP: 132 l := ordersafeexpr(n.Left, order) 133 if l == n.Left { 134 return n 135 } 136 a := *n 137 a.Orig = &a 138 a.Left = l 139 return typecheck(&a, Erv) 140 141 case ODOTPTR, OIND: 142 l := ordercheapexpr(n.Left, order) 143 if l == n.Left { 144 return n 145 } 146 a := *n 147 a.Orig = &a 148 a.Left = l 149 return typecheck(&a, Erv) 150 151 case OINDEX, OINDEXMAP: 152 var l *Node 153 if n.Left.Type.IsArray() { 154 l = ordersafeexpr(n.Left, order) 155 } else { 156 l = ordercheapexpr(n.Left, order) 157 } 158 r := ordercheapexpr(n.Right, order) 159 if l == n.Left && r == n.Right { 160 return n 161 } 162 a := *n 163 a.Orig = &a 164 a.Left = l 165 a.Right = r 166 return typecheck(&a, Erv) 167 default: 168 Fatalf("ordersafeexpr %v", n.Op) 169 return nil // not reached 170 } 171 } 172 173 // Isaddrokay reports whether it is okay to pass n's address to runtime routines. 174 // Taking the address of a variable makes the liveness and optimization analyses 175 // lose track of where the variable's lifetime ends. To avoid hurting the analyses 176 // of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay, 177 // because we emit explicit VARKILL instructions marking the end of those 178 // temporaries' lifetimes. 179 func isaddrokay(n *Node) bool { 180 return islvalue(n) && (n.Op != ONAME || n.Class == PEXTERN || n.IsAutoTmp()) 181 } 182 183 // Orderaddrtemp ensures that n is okay to pass by address to runtime routines. 184 // If the original argument n is not okay, orderaddrtemp creates a tmp, emits 185 // tmp = n, and then returns tmp. 186 // The result of orderaddrtemp MUST be assigned back to n, e.g. 187 // n.Left = orderaddrtemp(n.Left, order) 188 func orderaddrtemp(n *Node, order *Order) *Node { 189 if consttype(n) >= 0 { 190 // TODO: expand this to all static composite literal nodes? 191 n = defaultlit(n, nil) 192 dowidth(n.Type) 193 vstat := staticname(n.Type) 194 vstat.Name.Readonly = true 195 var out []*Node 196 staticassign(vstat, n, &out) 197 if out != nil { 198 Fatalf("staticassign of const generated code: %+v", n) 199 } 200 vstat = typecheck(vstat, Erv) 201 return vstat 202 } 203 if isaddrokay(n) { 204 return n 205 } 206 return ordercopyexpr(n, n.Type, order, 0) 207 } 208 209 // ordermapkeytemp prepares n.Right to be a key in a map lookup. 210 func ordermapkeytemp(n *Node, order *Order) { 211 // Most map calls need to take the address of the key. 212 // Exception: mapaccessN_fast* calls. See golang.org/issue/19015. 213 p, _ := mapaccessfast(n.Left.Type) 214 fastaccess := p != "" && n.Etype == 0 // Etype == 0 iff n is an rvalue 215 if fastaccess { 216 return 217 } 218 n.Right = orderaddrtemp(n.Right, order) 219 } 220 221 type ordermarker int 222 223 // Marktemp returns the top of the temporary variable stack. 224 func marktemp(order *Order) ordermarker { 225 return ordermarker(len(order.temp)) 226 } 227 228 // Poptemp pops temporaries off the stack until reaching the mark, 229 // which must have been returned by marktemp. 230 func poptemp(mark ordermarker, order *Order) { 231 order.temp = order.temp[:mark] 232 } 233 234 // Cleantempnopop emits to *out VARKILL instructions for each temporary 235 // above the mark on the temporary stack, but it does not pop them 236 // from the stack. 237 func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) { 238 var kill *Node 239 240 for i := len(order.temp) - 1; i >= int(mark); i-- { 241 n := order.temp[i] 242 if n.Name.Keepalive { 243 n.Name.Keepalive = false 244 n.Addrtaken = true // ensure SSA keeps the n variable 245 kill = nod(OVARLIVE, n, nil) 246 kill = typecheck(kill, Etop) 247 *out = append(*out, kill) 248 } 249 kill = nod(OVARKILL, n, nil) 250 kill = typecheck(kill, Etop) 251 *out = append(*out, kill) 252 } 253 } 254 255 // Cleantemp emits VARKILL instructions for each temporary above the 256 // mark on the temporary stack and removes them from the stack. 257 func cleantemp(top ordermarker, order *Order) { 258 cleantempnopop(top, order, &order.out) 259 poptemp(top, order) 260 } 261 262 // Orderstmtlist orders each of the statements in the list. 263 func orderstmtlist(l Nodes, order *Order) { 264 for _, n := range l.Slice() { 265 orderstmt(n, order) 266 } 267 } 268 269 // Orderblock orders the block of statements l onto a new list, 270 // and returns the ordered list. 271 func orderblock(l Nodes) []*Node { 272 var order Order 273 mark := marktemp(&order) 274 orderstmtlist(l, &order) 275 cleantemp(mark, &order) 276 return order.out 277 } 278 279 // OrderblockNodes orders the block of statements in n into a new slice, 280 // and then replaces the old slice in n with the new slice. 281 func orderblockNodes(n *Nodes) { 282 var order Order 283 mark := marktemp(&order) 284 orderstmtlist(*n, &order) 285 cleantemp(mark, &order) 286 n.Set(order.out) 287 } 288 289 // Orderexprinplace orders the side effects in *np and 290 // leaves them as the init list of the final *np. 291 // The result of orderexprinplace MUST be assigned back to n, e.g. 292 // n.Left = orderexprinplace(n.Left, outer) 293 func orderexprinplace(n *Node, outer *Order) *Node { 294 var order Order 295 n = orderexpr(n, &order, nil) 296 n = addinit(n, order.out) 297 298 // insert new temporaries from order 299 // at head of outer list. 300 outer.temp = append(outer.temp, order.temp...) 301 return n 302 } 303 304 // Orderstmtinplace orders the side effects of the single statement *np 305 // and replaces it with the resulting statement list. 306 // The result of orderstmtinplace MUST be assigned back to n, e.g. 307 // n.Left = orderstmtinplace(n.Left) 308 func orderstmtinplace(n *Node) *Node { 309 var order Order 310 mark := marktemp(&order) 311 orderstmt(n, &order) 312 cleantemp(mark, &order) 313 return liststmt(order.out) 314 } 315 316 // Orderinit moves n's init list to order->out. 317 func orderinit(n *Node, order *Order) { 318 orderstmtlist(n.Ninit, order) 319 n.Ninit.Set(nil) 320 } 321 322 // Ismulticall reports whether the list l is f() for a multi-value function. 323 // Such an f() could appear as the lone argument to a multi-arg function. 324 func ismulticall(l Nodes) bool { 325 // one arg only 326 if l.Len() != 1 { 327 return false 328 } 329 n := l.First() 330 331 // must be call 332 switch n.Op { 333 default: 334 return false 335 336 case OCALLFUNC, OCALLMETH, OCALLINTER: 337 break 338 } 339 340 // call must return multiple values 341 return n.Left.Type.Results().NumFields() > 1 342 } 343 344 // Copyret emits t1, t2, ... = n, where n is a function call, 345 // and then returns the list t1, t2, .... 346 func copyret(n *Node, order *Order) []*Node { 347 if !n.Type.IsFuncArgStruct() { 348 Fatalf("copyret %v %d", n.Type, n.Left.Type.Results().NumFields()) 349 } 350 351 var l1 []*Node 352 var l2 []*Node 353 for _, t := range n.Type.Fields().Slice() { 354 tmp := temp(t.Type) 355 l1 = append(l1, tmp) 356 l2 = append(l2, tmp) 357 } 358 359 as := nod(OAS2, nil, nil) 360 as.List.Set(l1) 361 as.Rlist.Set1(n) 362 as = typecheck(as, Etop) 363 orderstmt(as, order) 364 365 return l2 366 } 367 368 // Ordercallargs orders the list of call arguments *l. 369 func ordercallargs(l *Nodes, order *Order) { 370 if ismulticall(*l) { 371 // return f() where f() is multiple values. 372 l.Set(copyret(l.First(), order)) 373 } else { 374 orderexprlist(*l, order) 375 } 376 } 377 378 // Ordercall orders the call expression n. 379 // n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY. 380 func ordercall(n *Node, order *Order) { 381 n.Left = orderexpr(n.Left, order, nil) 382 n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp 383 ordercallargs(&n.List, order) 384 385 if n.Op == OCALLFUNC { 386 t, it := iterFields(n.Left.Type.Params()) 387 for i := range n.List.Slice() { 388 // Check for "unsafe-uintptr" tag provided by escape analysis. 389 // If present and the argument is really a pointer being converted 390 // to uintptr, arrange for the pointer to be kept alive until the call 391 // returns, by copying it into a temp and marking that temp 392 // still alive when we pop the temp stack. 393 if t == nil { 394 break 395 } 396 if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag { 397 xp := n.List.Addr(i) 398 for (*xp).Op == OCONVNOP && !(*xp).Type.IsPtr() { 399 xp = &(*xp).Left 400 } 401 x := *xp 402 if x.Type.IsPtr() { 403 x = ordercopyexpr(x, x.Type, order, 0) 404 x.Name.Keepalive = true 405 *xp = x 406 } 407 } 408 next := it.Next() 409 if next == nil && t.Isddd && t.Note == uintptrEscapesTag { 410 next = t 411 } 412 t = next 413 } 414 } 415 } 416 417 // Ordermapassign appends n to order->out, introducing temporaries 418 // to make sure that all map assignments have the form m[k] = x. 419 // (Note: orderexpr has already been called on n, so we know k is addressable.) 420 // 421 // If n is the multiple assignment form ..., m[k], ... = ..., the rewrite is 422 // t1 = m 423 // t2 = k 424 // ...., t3, ... = x 425 // t1[t2] = t3 426 // 427 // The temporaries t1, t2 are needed in case the ... being assigned 428 // contain m or k. They are usually unnecessary, but in the unnecessary 429 // cases they are also typically registerizable, so not much harm done. 430 // And this only applies to the multiple-assignment form. 431 // We could do a more precise analysis if needed, like in walk.go. 432 func ordermapassign(n *Node, order *Order) { 433 switch n.Op { 434 default: 435 Fatalf("ordermapassign %v", n.Op) 436 437 case OAS: 438 order.out = append(order.out, n) 439 440 case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC: 441 var post []*Node 442 var m *Node 443 var a *Node 444 for i1, n1 := range n.List.Slice() { 445 if n1.Op == OINDEXMAP { 446 m = n1 447 if !m.Left.IsAutoTmp() { 448 m.Left = ordercopyexpr(m.Left, m.Left.Type, order, 0) 449 } 450 if !m.Right.IsAutoTmp() { 451 m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0) 452 } 453 n.List.SetIndex(i1, ordertemp(m.Type, order, false)) 454 a = nod(OAS, m, n.List.Index(i1)) 455 a = typecheck(a, Etop) 456 post = append(post, a) 457 } else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) { 458 m = n.List.Index(i1) 459 t := ordertemp(m.Type, order, false) 460 n.List.SetIndex(i1, t) 461 a = nod(OAS, m, t) 462 a = typecheck(a, Etop) 463 post = append(post, a) 464 } 465 } 466 467 order.out = append(order.out, n) 468 order.out = append(order.out, post...) 469 } 470 } 471 472 // Orderstmt orders the statement n, appending to order->out. 473 // Temporaries created during the statement are cleaned 474 // up using VARKILL instructions as possible. 475 func orderstmt(n *Node, order *Order) { 476 if n == nil { 477 return 478 } 479 480 lno := setlineno(n) 481 482 orderinit(n, order) 483 484 switch n.Op { 485 default: 486 Fatalf("orderstmt %v", n.Op) 487 488 case OVARKILL, OVARLIVE: 489 order.out = append(order.out, n) 490 491 case OAS: 492 t := marktemp(order) 493 n.Left = orderexpr(n.Left, order, nil) 494 n.Right = orderexpr(n.Right, order, n.Left) 495 ordermapassign(n, order) 496 cleantemp(t, order) 497 498 case OAS2, 499 OCLOSE, 500 OCOPY, 501 OPRINT, 502 OPRINTN, 503 ORECOVER, 504 ORECV: 505 t := marktemp(order) 506 n.Left = orderexpr(n.Left, order, nil) 507 n.Right = orderexpr(n.Right, order, nil) 508 orderexprlist(n.List, order) 509 orderexprlist(n.Rlist, order) 510 switch n.Op { 511 case OAS2: 512 ordermapassign(n, order) 513 default: 514 order.out = append(order.out, n) 515 } 516 cleantemp(t, order) 517 518 case OASOP: 519 // Special: rewrite l op= r into l = l op r. 520 // This simplifies quite a few operations; 521 // most important is that it lets us separate 522 // out map read from map write when l is 523 // a map index expression. 524 t := marktemp(order) 525 526 n.Left = orderexpr(n.Left, order, nil) 527 n.Left = ordersafeexpr(n.Left, order) 528 tmp1 := treecopy(n.Left, src.NoXPos) 529 if tmp1.Op == OINDEXMAP { 530 tmp1.Etype = 0 // now an rvalue not an lvalue 531 } 532 tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0) 533 // TODO(marvin): Fix Node.EType type union. 534 n.Right = nod(Op(n.Etype), tmp1, n.Right) 535 n.Right = typecheck(n.Right, Erv) 536 n.Right = orderexpr(n.Right, order, nil) 537 n.Etype = 0 538 n.Op = OAS 539 ordermapassign(n, order) 540 cleantemp(t, order) 541 542 // Special: make sure key is addressable if needed, 543 // and make sure OINDEXMAP is not copied out. 544 case OAS2MAPR: 545 t := marktemp(order) 546 547 orderexprlist(n.List, order) 548 r := n.Rlist.First() 549 r.Left = orderexpr(r.Left, order, nil) 550 r.Right = orderexpr(r.Right, order, nil) 551 552 // See case OINDEXMAP below. 553 if r.Right.Op == OARRAYBYTESTR { 554 r.Right.Op = OARRAYBYTESTRTMP 555 } 556 ordermapkeytemp(r, order) 557 orderokas2(n, order) 558 cleantemp(t, order) 559 560 // Special: avoid copy of func call n->rlist->n. 561 case OAS2FUNC: 562 t := marktemp(order) 563 564 orderexprlist(n.List, order) 565 ordercall(n.Rlist.First(), order) 566 orderas2(n, order) 567 cleantemp(t, order) 568 569 // Special: use temporary variables to hold result, 570 // so that assertI2Tetc can take address of temporary. 571 // No temporary for blank assignment. 572 case OAS2DOTTYPE: 573 t := marktemp(order) 574 575 orderexprlist(n.List, order) 576 n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T) 577 orderokas2(n, order) 578 cleantemp(t, order) 579 580 // Special: use temporary variables to hold result, 581 // so that chanrecv can take address of temporary. 582 case OAS2RECV: 583 t := marktemp(order) 584 585 orderexprlist(n.List, order) 586 n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv 587 ch := n.Rlist.First().Left.Type 588 tmp1 := ordertemp(ch.Elem(), order, haspointers(ch.Elem())) 589 tmp2 := ordertemp(Types[TBOOL], order, false) 590 order.out = append(order.out, n) 591 r := nod(OAS, n.List.First(), tmp1) 592 r = typecheck(r, Etop) 593 ordermapassign(r, order) 594 r = okas(n.List.Second(), tmp2) 595 r = typecheck(r, Etop) 596 ordermapassign(r, order) 597 n.List.Set([]*Node{tmp1, tmp2}) 598 cleantemp(t, order) 599 600 // Special: does not save n onto out. 601 case OBLOCK, OEMPTY: 602 orderstmtlist(n.List, order) 603 604 // Special: n->left is not an expression; save as is. 605 case OBREAK, 606 OCONTINUE, 607 ODCL, 608 ODCLCONST, 609 ODCLTYPE, 610 OFALL, 611 OXFALL, 612 OGOTO, 613 OLABEL, 614 ORETJMP: 615 order.out = append(order.out, n) 616 617 // Special: handle call arguments. 618 case OCALLFUNC, OCALLINTER, OCALLMETH: 619 t := marktemp(order) 620 621 ordercall(n, order) 622 order.out = append(order.out, n) 623 cleantemp(t, order) 624 625 // Special: order arguments to inner call but not call itself. 626 case ODEFER, OPROC: 627 t := marktemp(order) 628 629 switch n.Left.Op { 630 // Delete will take the address of the key. 631 // Copy key into new temp and do not clean it 632 // (it persists beyond the statement). 633 case ODELETE: 634 orderexprlist(n.Left.List, order) 635 636 t1 := marktemp(order) 637 np := n.Left.List.Addr(1) // map key 638 *np = ordercopyexpr(*np, (*np).Type, order, 0) 639 poptemp(t1, order) 640 641 default: 642 ordercall(n.Left, order) 643 } 644 645 order.out = append(order.out, n) 646 cleantemp(t, order) 647 648 case ODELETE: 649 t := marktemp(order) 650 n.List.SetIndex(0, orderexpr(n.List.Index(0), order, nil)) 651 n.List.SetIndex(1, orderexpr(n.List.Index(1), order, nil)) 652 n.List.SetIndex(1, orderaddrtemp(n.List.Index(1), order)) // map key 653 order.out = append(order.out, n) 654 cleantemp(t, order) 655 656 // Clean temporaries from condition evaluation at 657 // beginning of loop body and after for statement. 658 case OFOR: 659 t := marktemp(order) 660 661 n.Left = orderexprinplace(n.Left, order) 662 var l []*Node 663 cleantempnopop(t, order, &l) 664 n.Nbody.Prepend(l...) 665 orderblockNodes(&n.Nbody) 666 n.Right = orderstmtinplace(n.Right) 667 order.out = append(order.out, n) 668 cleantemp(t, order) 669 670 // Clean temporaries from condition at 671 // beginning of both branches. 672 case OIF: 673 t := marktemp(order) 674 675 n.Left = orderexprinplace(n.Left, order) 676 var l []*Node 677 cleantempnopop(t, order, &l) 678 n.Nbody.Prepend(l...) 679 l = nil 680 cleantempnopop(t, order, &l) 681 n.Rlist.Prepend(l...) 682 poptemp(t, order) 683 orderblockNodes(&n.Nbody) 684 n.Rlist.Set(orderblock(n.Rlist)) 685 order.out = append(order.out, n) 686 687 // Special: argument will be converted to interface using convT2E 688 // so make sure it is an addressable temporary. 689 case OPANIC: 690 t := marktemp(order) 691 692 n.Left = orderexpr(n.Left, order, nil) 693 if !n.Left.Type.IsInterface() { 694 n.Left = orderaddrtemp(n.Left, order) 695 } 696 order.out = append(order.out, n) 697 cleantemp(t, order) 698 699 case ORANGE: 700 // n.Right is the expression being ranged over. 701 // order it, and then make a copy if we need one. 702 // We almost always do, to ensure that we don't 703 // see any value changes made during the loop. 704 // Usually the copy is cheap (e.g., array pointer, 705 // chan, slice, string are all tiny). 706 // The exception is ranging over an array value 707 // (not a slice, not a pointer to array), 708 // which must make a copy to avoid seeing updates made during 709 // the range body. Ranging over an array value is uncommon though. 710 711 // Mark []byte(str) range expression to reuse string backing storage. 712 // It is safe because the storage cannot be mutated. 713 if n.Right.Op == OSTRARRAYBYTE { 714 n.Right.Op = OSTRARRAYBYTETMP 715 } 716 717 t := marktemp(order) 718 n.Right = orderexpr(n.Right, order, nil) 719 switch n.Type.Etype { 720 default: 721 Fatalf("orderstmt range %v", n.Type) 722 723 case TARRAY, TSLICE: 724 if n.List.Len() < 2 || isblank(n.List.Second()) { 725 // for i := range x will only use x once, to compute len(x). 726 // No need to copy it. 727 break 728 } 729 fallthrough 730 731 case TCHAN, TSTRING: 732 // chan, string, slice, array ranges use value multiple times. 733 // make copy. 734 r := n.Right 735 736 if r.Type.IsString() && r.Type != Types[TSTRING] { 737 r = nod(OCONV, r, nil) 738 r.Type = Types[TSTRING] 739 r = typecheck(r, Erv) 740 } 741 742 n.Right = ordercopyexpr(r, r.Type, order, 0) 743 744 case TMAP: 745 // copy the map value in case it is a map literal. 746 // TODO(rsc): Make tmp = literal expressions reuse tmp. 747 // For maps tmp is just one word so it hardly matters. 748 r := n.Right 749 n.Right = ordercopyexpr(r, r.Type, order, 0) 750 751 // n->alloc is the temp for the iterator. 752 prealloc[n] = ordertemp(Types[TUINT8], order, true) 753 } 754 for i := range n.List.Slice() { 755 n.List.SetIndex(i, orderexprinplace(n.List.Index(i), order)) 756 } 757 orderblockNodes(&n.Nbody) 758 order.out = append(order.out, n) 759 cleantemp(t, order) 760 761 case ORETURN: 762 ordercallargs(&n.List, order) 763 order.out = append(order.out, n) 764 765 // Special: clean case temporaries in each block entry. 766 // Select must enter one of its blocks, so there is no 767 // need for a cleaning at the end. 768 // Doubly special: evaluation order for select is stricter 769 // than ordinary expressions. Even something like p.c 770 // has to be hoisted into a temporary, so that it cannot be 771 // reordered after the channel evaluation for a different 772 // case (if p were nil, then the timing of the fault would 773 // give this away). 774 case OSELECT: 775 t := marktemp(order) 776 777 var tmp1 *Node 778 var tmp2 *Node 779 var r *Node 780 for _, n2 := range n.List.Slice() { 781 if n2.Op != OXCASE { 782 Fatalf("order select case %v", n2.Op) 783 } 784 r = n2.Left 785 setlineno(n2) 786 787 // Append any new body prologue to ninit. 788 // The next loop will insert ninit into nbody. 789 if n2.Ninit.Len() != 0 { 790 Fatalf("order select ninit") 791 } 792 if r != nil { 793 switch r.Op { 794 default: 795 yyerror("unknown op in select %v", r.Op) 796 Dump("select case", r) 797 798 // If this is case x := <-ch or case x, y := <-ch, the case has 799 // the ODCL nodes to declare x and y. We want to delay that 800 // declaration (and possible allocation) until inside the case body. 801 // Delete the ODCL nodes here and recreate them inside the body below. 802 case OSELRECV, OSELRECV2: 803 if r.Colas { 804 i := 0 805 if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left { 806 i++ 807 } 808 if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() { 809 i++ 810 } 811 if i >= r.Ninit.Len() { 812 r.Ninit.Set(nil) 813 } 814 } 815 816 if r.Ninit.Len() != 0 { 817 yyerror("ninit on select recv") 818 dumplist("ninit", r.Ninit) 819 } 820 821 // case x = <-c 822 // case x, ok = <-c 823 // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c. 824 // r->left == N means 'case <-c'. 825 // c is always evaluated; x and ok are only evaluated when assigned. 826 r.Right.Left = orderexpr(r.Right.Left, order, nil) 827 828 if r.Right.Left.Op != ONAME { 829 r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0) 830 } 831 832 // Introduce temporary for receive and move actual copy into case body. 833 // avoids problems with target being addressed, as usual. 834 // NOTE: If we wanted to be clever, we could arrange for just one 835 // temporary per distinct type, sharing the temp among all receives 836 // with that temp. Similarly one ok bool could be shared among all 837 // the x,ok receives. Not worth doing until there's a clear need. 838 if r.Left != nil && isblank(r.Left) { 839 r.Left = nil 840 } 841 if r.Left != nil { 842 // use channel element type for temporary to avoid conversions, 843 // such as in case interfacevalue = <-intchan. 844 // the conversion happens in the OAS instead. 845 tmp1 = r.Left 846 847 if r.Colas { 848 tmp2 = nod(ODCL, tmp1, nil) 849 tmp2 = typecheck(tmp2, Etop) 850 n2.Ninit.Append(tmp2) 851 } 852 853 r.Left = ordertemp(r.Right.Left.Type.Elem(), order, haspointers(r.Right.Left.Type.Elem())) 854 tmp2 = nod(OAS, tmp1, r.Left) 855 tmp2 = typecheck(tmp2, Etop) 856 n2.Ninit.Append(tmp2) 857 } 858 859 if r.List.Len() != 0 && isblank(r.List.First()) { 860 r.List.Set(nil) 861 } 862 if r.List.Len() != 0 { 863 tmp1 = r.List.First() 864 if r.Colas { 865 tmp2 = nod(ODCL, tmp1, nil) 866 tmp2 = typecheck(tmp2, Etop) 867 n2.Ninit.Append(tmp2) 868 } 869 870 r.List.Set1(ordertemp(Types[TBOOL], order, false)) 871 tmp2 = okas(tmp1, r.List.First()) 872 tmp2 = typecheck(tmp2, Etop) 873 n2.Ninit.Append(tmp2) 874 } 875 n2.Ninit.Set(orderblock(n2.Ninit)) 876 877 case OSEND: 878 if r.Ninit.Len() != 0 { 879 yyerror("ninit on select send") 880 dumplist("ninit", r.Ninit) 881 } 882 883 // case c <- x 884 // r->left is c, r->right is x, both are always evaluated. 885 r.Left = orderexpr(r.Left, order, nil) 886 887 if !r.Left.IsAutoTmp() { 888 r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0) 889 } 890 r.Right = orderexpr(r.Right, order, nil) 891 if !r.Right.IsAutoTmp() { 892 r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0) 893 } 894 } 895 } 896 897 orderblockNodes(&n2.Nbody) 898 } 899 // Now that we have accumulated all the temporaries, clean them. 900 // Also insert any ninit queued during the previous loop. 901 // (The temporary cleaning must follow that ninit work.) 902 for _, n3 := range n.List.Slice() { 903 s := n3.Ninit.Slice() 904 cleantempnopop(t, order, &s) 905 n3.Nbody.Prepend(s...) 906 n3.Ninit.Set(nil) 907 } 908 909 order.out = append(order.out, n) 910 poptemp(t, order) 911 912 // Special: value being sent is passed as a pointer; make it addressable. 913 case OSEND: 914 t := marktemp(order) 915 916 n.Left = orderexpr(n.Left, order, nil) 917 n.Right = orderexpr(n.Right, order, nil) 918 n.Right = orderaddrtemp(n.Right, order) 919 order.out = append(order.out, n) 920 cleantemp(t, order) 921 922 // TODO(rsc): Clean temporaries more aggressively. 923 // Note that because walkswitch will rewrite some of the 924 // switch into a binary search, this is not as easy as it looks. 925 // (If we ran that code here we could invoke orderstmt on 926 // the if-else chain instead.) 927 // For now just clean all the temporaries at the end. 928 // In practice that's fine. 929 case OSWITCH: 930 t := marktemp(order) 931 932 n.Left = orderexpr(n.Left, order, nil) 933 for _, n4 := range n.List.Slice() { 934 if n4.Op != OXCASE { 935 Fatalf("order switch case %v", n4.Op) 936 } 937 orderexprlistinplace(n4.List, order) 938 orderblockNodes(&n4.Nbody) 939 } 940 941 order.out = append(order.out, n) 942 cleantemp(t, order) 943 } 944 945 lineno = lno 946 } 947 948 // Orderexprlist orders the expression list l into order. 949 func orderexprlist(l Nodes, order *Order) { 950 s := l.Slice() 951 for i := range s { 952 s[i] = orderexpr(s[i], order, nil) 953 } 954 } 955 956 // Orderexprlist orders the expression list l but saves 957 // the side effects on the individual expression ninit lists. 958 func orderexprlistinplace(l Nodes, order *Order) { 959 s := l.Slice() 960 for i := range s { 961 s[i] = orderexprinplace(s[i], order) 962 } 963 } 964 965 // prealloc[x] records the allocation to use for x. 966 var prealloc = map[*Node]*Node{} 967 968 // Orderexpr orders a single expression, appending side 969 // effects to order->out as needed. 970 // If this is part of an assignment lhs = *np, lhs is given. 971 // Otherwise lhs == nil. (When lhs != nil it may be possible 972 // to avoid copying the result of the expression to a temporary.) 973 // The result of orderexpr MUST be assigned back to n, e.g. 974 // n.Left = orderexpr(n.Left, order, lhs) 975 func orderexpr(n *Node, order *Order, lhs *Node) *Node { 976 if n == nil { 977 return n 978 } 979 980 lno := setlineno(n) 981 orderinit(n, order) 982 983 switch n.Op { 984 default: 985 n.Left = orderexpr(n.Left, order, nil) 986 n.Right = orderexpr(n.Right, order, nil) 987 orderexprlist(n.List, order) 988 orderexprlist(n.Rlist, order) 989 990 // Addition of strings turns into a function call. 991 // Allocate a temporary to hold the strings. 992 // Fewer than 5 strings use direct runtime helpers. 993 case OADDSTR: 994 orderexprlist(n.List, order) 995 996 if n.List.Len() > 5 { 997 t := typArray(Types[TSTRING], int64(n.List.Len())) 998 prealloc[n] = ordertemp(t, order, false) 999 } 1000 1001 // Mark string(byteSlice) arguments to reuse byteSlice backing 1002 // buffer during conversion. String concatenation does not 1003 // memorize the strings for later use, so it is safe. 1004 // However, we can do it only if there is at least one non-empty string literal. 1005 // Otherwise if all other arguments are empty strings, 1006 // concatstrings will return the reference to the temp string 1007 // to the caller. 1008 hasbyte := false 1009 1010 haslit := false 1011 for _, n1 := range n.List.Slice() { 1012 hasbyte = hasbyte || n1.Op == OARRAYBYTESTR 1013 haslit = haslit || n1.Op == OLITERAL && len(n1.Val().U.(string)) != 0 1014 } 1015 1016 if haslit && hasbyte { 1017 for _, n2 := range n.List.Slice() { 1018 if n2.Op == OARRAYBYTESTR { 1019 n2.Op = OARRAYBYTESTRTMP 1020 } 1021 } 1022 } 1023 1024 case OCMPSTR: 1025 n.Left = orderexpr(n.Left, order, nil) 1026 n.Right = orderexpr(n.Right, order, nil) 1027 1028 // Mark string(byteSlice) arguments to reuse byteSlice backing 1029 // buffer during conversion. String comparison does not 1030 // memorize the strings for later use, so it is safe. 1031 if n.Left.Op == OARRAYBYTESTR { 1032 n.Left.Op = OARRAYBYTESTRTMP 1033 } 1034 if n.Right.Op == OARRAYBYTESTR { 1035 n.Right.Op = OARRAYBYTESTRTMP 1036 } 1037 1038 // key must be addressable 1039 case OINDEXMAP: 1040 n.Left = orderexpr(n.Left, order, nil) 1041 n.Right = orderexpr(n.Right, order, nil) 1042 needCopy := false 1043 1044 if n.Etype == 0 && instrumenting { 1045 // Race detector needs the copy so it can 1046 // call treecopy on the result. 1047 needCopy = true 1048 } 1049 1050 // For x = m[string(k)] where k is []byte, the allocation of 1051 // backing bytes for the string can be avoided by reusing 1052 // the []byte backing array. This is a special case that it 1053 // would be nice to handle more generally, but because 1054 // there are no []byte-keyed maps, this specific case comes 1055 // up in important cases in practice. See issue 3512. 1056 // Nothing can change the []byte we are not copying before 1057 // the map index, because the map access is going to 1058 // be forced to happen immediately following this 1059 // conversion (by the ordercopyexpr a few lines below). 1060 if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR { 1061 n.Right.Op = OARRAYBYTESTRTMP 1062 needCopy = true 1063 } 1064 1065 ordermapkeytemp(n, order) 1066 if needCopy { 1067 n = ordercopyexpr(n, n.Type, order, 0) 1068 } 1069 1070 // concrete type (not interface) argument must be addressable 1071 // temporary to pass to runtime. 1072 case OCONVIFACE: 1073 n.Left = orderexpr(n.Left, order, nil) 1074 1075 if !n.Left.Type.IsInterface() { 1076 n.Left = orderaddrtemp(n.Left, order) 1077 } 1078 1079 case OCONVNOP: 1080 if n.Type.IsKind(TUNSAFEPTR) && n.Left.Type.IsKind(TUINTPTR) && (n.Left.Op == OCALLFUNC || n.Left.Op == OCALLINTER || n.Left.Op == OCALLMETH) { 1081 // When reordering unsafe.Pointer(f()) into a separate 1082 // statement, the conversion and function call must stay 1083 // together. See golang.org/issue/15329. 1084 orderinit(n.Left, order) 1085 ordercall(n.Left, order) 1086 if lhs == nil || lhs.Op != ONAME || instrumenting { 1087 n = ordercopyexpr(n, n.Type, order, 0) 1088 } 1089 } else { 1090 n.Left = orderexpr(n.Left, order, nil) 1091 } 1092 1093 case OANDAND, OOROR: 1094 mark := marktemp(order) 1095 n.Left = orderexpr(n.Left, order, nil) 1096 1097 // Clean temporaries from first branch at beginning of second. 1098 // Leave them on the stack so that they can be killed in the outer 1099 // context in case the short circuit is taken. 1100 var s []*Node 1101 1102 cleantempnopop(mark, order, &s) 1103 n.Right.Ninit.Prepend(s...) 1104 n.Right = orderexprinplace(n.Right, order) 1105 1106 case OCALLFUNC, 1107 OCALLINTER, 1108 OCALLMETH, 1109 OCAP, 1110 OCOMPLEX, 1111 OCOPY, 1112 OIMAG, 1113 OLEN, 1114 OMAKECHAN, 1115 OMAKEMAP, 1116 OMAKESLICE, 1117 ONEW, 1118 OREAL, 1119 ORECOVER, 1120 OSTRARRAYBYTE, 1121 OSTRARRAYBYTETMP, 1122 OSTRARRAYRUNE: 1123 ordercall(n, order) 1124 if lhs == nil || lhs.Op != ONAME || instrumenting { 1125 n = ordercopyexpr(n, n.Type, order, 0) 1126 } 1127 1128 case OAPPEND: 1129 ordercallargs(&n.List, order) 1130 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) { 1131 n = ordercopyexpr(n, n.Type, order, 0) 1132 } 1133 1134 case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: 1135 n.Left = orderexpr(n.Left, order, nil) 1136 low, high, max := n.SliceBounds() 1137 low = orderexpr(low, order, nil) 1138 low = ordercheapexpr(low, order) 1139 high = orderexpr(high, order, nil) 1140 high = ordercheapexpr(high, order) 1141 max = orderexpr(max, order, nil) 1142 max = ordercheapexpr(max, order) 1143 n.SetSliceBounds(low, high, max) 1144 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { 1145 n = ordercopyexpr(n, n.Type, order, 0) 1146 } 1147 1148 case OCLOSURE: 1149 if n.Noescape && n.Func.Cvars.Len() > 0 { 1150 prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type 1151 } 1152 1153 case OARRAYLIT, OSLICELIT, OCALLPART: 1154 n.Left = orderexpr(n.Left, order, nil) 1155 n.Right = orderexpr(n.Right, order, nil) 1156 orderexprlist(n.List, order) 1157 orderexprlist(n.Rlist, order) 1158 if n.Noescape { 1159 prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type 1160 } 1161 1162 case ODDDARG: 1163 if n.Noescape { 1164 // The ddd argument does not live beyond the call it is created for. 1165 // Allocate a temporary that will be cleaned up when this statement 1166 // completes. We could be more aggressive and try to arrange for it 1167 // to be cleaned up when the call completes. 1168 prealloc[n] = ordertemp(n.Type.Elem(), order, false) 1169 } 1170 1171 case ODOTTYPE, ODOTTYPE2: 1172 n.Left = orderexpr(n.Left, order, nil) 1173 // TODO(rsc): The isfat is for consistency with componentgen and walkexpr. 1174 // It needs to be removed in all three places. 1175 // That would allow inlining x.(struct{*int}) the same as x.(*int). 1176 if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting { 1177 n = ordercopyexpr(n, n.Type, order, 1) 1178 } 1179 1180 case ORECV: 1181 n.Left = orderexpr(n.Left, order, nil) 1182 n = ordercopyexpr(n, n.Type, order, 1) 1183 1184 case OEQ, ONE: 1185 n.Left = orderexpr(n.Left, order, nil) 1186 n.Right = orderexpr(n.Right, order, nil) 1187 t := n.Left.Type 1188 if t.IsStruct() || t.IsArray() { 1189 // for complex comparisons, we need both args to be 1190 // addressable so we can pass them to the runtime. 1191 n.Left = orderaddrtemp(n.Left, order) 1192 n.Right = orderaddrtemp(n.Right, order) 1193 } 1194 } 1195 1196 lineno = lno 1197 return n 1198 } 1199 1200 // okas creates and returns an assignment of val to ok, 1201 // including an explicit conversion if necessary. 1202 func okas(ok, val *Node) *Node { 1203 if !isblank(ok) { 1204 val = conv(val, ok.Type) 1205 } 1206 return nod(OAS, ok, val) 1207 } 1208 1209 // orderas2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment. 1210 // The caller should order the right-hand side of the assignment before calling orderas2. 1211 // It rewrites, 1212 // a, b, a = ... 1213 // as 1214 // tmp1, tmp2, tmp3 = ... 1215 // a, b, a = tmp1, tmp2, tmp3 1216 // This is necessary to ensure left to right assignment order. 1217 func orderas2(n *Node, order *Order) { 1218 tmplist := []*Node{} 1219 left := []*Node{} 1220 for _, l := range n.List.Slice() { 1221 if !isblank(l) { 1222 tmp := ordertemp(l.Type, order, haspointers(l.Type)) 1223 tmplist = append(tmplist, tmp) 1224 left = append(left, l) 1225 } 1226 } 1227 1228 order.out = append(order.out, n) 1229 1230 as := nod(OAS2, nil, nil) 1231 as.List.Set(left) 1232 as.Rlist.Set(tmplist) 1233 as = typecheck(as, Etop) 1234 orderstmt(as, order) 1235 1236 ti := 0 1237 for ni, l := range n.List.Slice() { 1238 if !isblank(l) { 1239 n.List.SetIndex(ni, tmplist[ti]) 1240 ti++ 1241 } 1242 } 1243 } 1244 1245 // orderokas2 orders OAS2 with ok. 1246 // Just like orderas2(), this also adds temporaries to ensure left-to-right assignment. 1247 func orderokas2(n *Node, order *Order) { 1248 var tmp1, tmp2 *Node 1249 if !isblank(n.List.First()) { 1250 typ := n.Rlist.First().Type 1251 tmp1 = ordertemp(typ, order, haspointers(typ)) 1252 } 1253 1254 if !isblank(n.List.Second()) { 1255 tmp2 = ordertemp(Types[TBOOL], order, false) 1256 } 1257 1258 order.out = append(order.out, n) 1259 1260 if tmp1 != nil { 1261 r := nod(OAS, n.List.First(), tmp1) 1262 r = typecheck(r, Etop) 1263 ordermapassign(r, order) 1264 n.List.SetIndex(0, tmp1) 1265 } 1266 if tmp2 != nil { 1267 r := okas(n.List.Second(), tmp2) 1268 r = typecheck(r, Etop) 1269 ordermapassign(r, order) 1270 n.List.SetIndex(1, tmp2) 1271 } 1272 }