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