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