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