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