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