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