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