github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/cmd/compile/internal/gc/order.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gc 6 7 import ( 8 "cmd/compile/internal/types" 9 "cmd/internal/src" 10 "fmt" 11 ) 12 13 // Rewrite tree to use separate statements to enforce 14 // order of evaluation. Makes walk easier, because it 15 // can (after this runs) reorder at will within an expression. 16 // 17 // Rewrite x op= y into x = x op y. 18 // 19 // Introduce temporaries as needed by runtime routines. 20 // For example, the map runtime routines take the map key 21 // by reference, so make sure all map keys are addressable 22 // by copying them to temporaries as needed. 23 // The same is true for channel operations. 24 // 25 // Arrange that map index expressions only appear in direct 26 // assignments x = m[k] or m[k] = x, never in larger expressions. 27 // 28 // Arrange that receive expressions only appear in direct assignments 29 // x = <-c or as standalone statements <-c, never in larger expressions. 30 31 // TODO(rsc): The temporary introduction during multiple assignments 32 // should be moved into this file, so that the temporaries can be cleaned 33 // and so that conversions implicit in the OAS2FUNC and OAS2RECV 34 // nodes can be made explicit and then have their temporaries cleaned. 35 36 // TODO(rsc): Goto and multilevel break/continue can jump over 37 // inserted VARKILL annotations. Work out a way to handle these. 38 // The current implementation is safe, in that it will execute correctly. 39 // But it won't reuse temporaries as aggressively as it might, and 40 // it can result in unnecessary zeroing of those variables in the function 41 // prologue. 42 43 // Order holds state during the ordering process. 44 type Order struct { 45 out []*Node // list of generated statements 46 temp []*Node // stack of temporary variables 47 } 48 49 // Order rewrites fn->nbody to apply the ordering constraints 50 // described in the comment at the top of the file. 51 func order(fn *Node) { 52 if Debug['W'] > 1 { 53 s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym) 54 dumplist(s, fn.Nbody) 55 } 56 57 orderblockNodes(&fn.Nbody) 58 } 59 60 // Ordertemp allocates a new temporary with the given type, 61 // pushes it onto the temp stack, and returns it. 62 // If clear is true, ordertemp emits code to zero the temporary. 63 func ordertemp(t *types.Type, order *Order, clear bool) *Node { 64 var_ := temp(t) 65 if clear { 66 a := nod(OAS, var_, nil) 67 a = typecheck(a, Etop) 68 order.out = append(order.out, a) 69 } 70 71 order.temp = append(order.temp, var_) 72 return var_ 73 } 74 75 // Ordercopyexpr behaves like ordertemp but also emits 76 // code to initialize the temporary to the value n. 77 // 78 // The clear argument is provided for use when the evaluation 79 // of tmp = n turns into a function call that is passed a pointer 80 // to the temporary as the output space. If the call blocks before 81 // tmp has been written, the garbage collector will still treat the 82 // temporary as live, so we must zero it before entering that call. 83 // Today, this only happens for channel receive operations. 84 // (The other candidate would be map access, but map access 85 // returns a pointer to the result data instead of taking a pointer 86 // to be filled in.) 87 func ordercopyexpr(n *Node, t *types.Type, order *Order, clear int) *Node { 88 var_ := ordertemp(t, order, clear != 0) 89 a := nod(OAS, var_, n) 90 a = typecheck(a, Etop) 91 order.out = append(order.out, a) 92 return var_ 93 } 94 95 // Ordercheapexpr returns a cheap version of n. 96 // The definition of cheap is that n is a variable or constant. 97 // If not, ordercheapexpr allocates a new tmp, emits tmp = n, 98 // and then returns tmp. 99 func ordercheapexpr(n *Node, order *Order) *Node { 100 if n == nil { 101 return nil 102 } 103 switch n.Op { 104 case ONAME, OLITERAL: 105 return n 106 case OLEN, OCAP: 107 l := ordercheapexpr(n.Left, order) 108 if l == n.Left { 109 return n 110 } 111 a := *n 112 a.Orig = &a 113 a.Left = l 114 return typecheck(&a, Erv) 115 } 116 117 return ordercopyexpr(n, n.Type, order, 0) 118 } 119 120 // Ordersafeexpr returns a safe version of n. 121 // The definition of safe is that n can appear multiple times 122 // without violating the semantics of the original program, 123 // and that assigning to the safe version has the same effect 124 // as assigning to the original n. 125 // 126 // The intended use is to apply to x when rewriting x += y into x = x + y. 127 func ordersafeexpr(n *Node, order *Order) *Node { 128 switch n.Op { 129 case ONAME, OLITERAL: 130 return n 131 132 case ODOT, OLEN, OCAP: 133 l := ordersafeexpr(n.Left, order) 134 if l == n.Left { 135 return n 136 } 137 a := *n 138 a.Orig = &a 139 a.Left = l 140 return typecheck(&a, Erv) 141 142 case ODOTPTR, OIND: 143 l := ordercheapexpr(n.Left, order) 144 if l == n.Left { 145 return n 146 } 147 a := *n 148 a.Orig = &a 149 a.Left = l 150 return typecheck(&a, Erv) 151 152 case OINDEX, OINDEXMAP: 153 var l *Node 154 if n.Left.Type.IsArray() { 155 l = ordersafeexpr(n.Left, order) 156 } else { 157 l = ordercheapexpr(n.Left, order) 158 } 159 r := ordercheapexpr(n.Right, order) 160 if l == n.Left && r == n.Right { 161 return n 162 } 163 a := *n 164 a.Orig = &a 165 a.Left = l 166 a.Right = r 167 return typecheck(&a, Erv) 168 default: 169 Fatalf("ordersafeexpr %v", n.Op) 170 return nil // not reached 171 } 172 } 173 174 // Isaddrokay reports whether it is okay to pass n's address to runtime routines. 175 // Taking the address of a variable makes the liveness and optimization analyses 176 // lose track of where the variable's lifetime ends. To avoid hurting the analyses 177 // of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay, 178 // because we emit explicit VARKILL instructions marking the end of those 179 // temporaries' lifetimes. 180 func isaddrokay(n *Node) bool { 181 return islvalue(n) && (n.Op != ONAME || n.Class() == PEXTERN || n.IsAutoTmp()) 182 } 183 184 // Orderaddrtemp ensures that n is okay to pass by address to runtime routines. 185 // If the original argument n is not okay, orderaddrtemp creates a tmp, emits 186 // tmp = n, and then returns tmp. 187 // The result of orderaddrtemp MUST be assigned back to n, e.g. 188 // n.Left = orderaddrtemp(n.Left, order) 189 func orderaddrtemp(n *Node, order *Order) *Node { 190 if consttype(n) > 0 { 191 // TODO: expand this to all static composite literal nodes? 192 n = defaultlit(n, nil) 193 dowidth(n.Type) 194 vstat := staticname(n.Type) 195 vstat.Name.SetReadonly(true) 196 var out []*Node 197 staticassign(vstat, n, &out) 198 if out != nil { 199 Fatalf("staticassign of const generated code: %+v", n) 200 } 201 vstat = typecheck(vstat, Erv) 202 return vstat 203 } 204 if isaddrokay(n) { 205 return n 206 } 207 return ordercopyexpr(n, n.Type, order, 0) 208 } 209 210 // ordermapkeytemp prepares n to be a key in a map runtime call and returns n. 211 // It should only be used for map runtime calls which have *_fast* versions. 212 func ordermapkeytemp(t *types.Type, n *Node, order *Order) *Node { 213 // Most map calls need to take the address of the key. 214 // Exception: map*_fast* calls. See golang.org/issue/19015. 215 if mapfast(t) == mapslow { 216 return orderaddrtemp(n, order) 217 } 218 return n 219 } 220 221 type ordermarker int 222 223 // Marktemp returns the top of the temporary variable stack. 224 func marktemp(order *Order) ordermarker { 225 return ordermarker(len(order.temp)) 226 } 227 228 // Poptemp pops temporaries off the stack until reaching the mark, 229 // which must have been returned by marktemp. 230 func poptemp(mark ordermarker, order *Order) { 231 order.temp = order.temp[:mark] 232 } 233 234 // Cleantempnopop emits to *out VARKILL instructions for each temporary 235 // above the mark on the temporary stack, but it does not pop them 236 // from the stack. 237 func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) { 238 for i := len(order.temp) - 1; i >= int(mark); i-- { 239 n := order.temp[i] 240 if n.Name.Keepalive() { 241 n.Name.SetKeepalive(false) 242 n.SetAddrtaken(true) // ensure SSA keeps the n variable 243 kill := nod(OVARLIVE, n, nil) 244 kill = typecheck(kill, Etop) 245 *out = append(*out, kill) 246 } 247 kill := nod(OVARKILL, n, nil) 248 kill = typecheck(kill, Etop) 249 *out = append(*out, kill) 250 } 251 } 252 253 // Cleantemp emits VARKILL instructions for each temporary above the 254 // mark on the temporary stack and removes them from the stack. 255 func cleantemp(top ordermarker, order *Order) { 256 cleantempnopop(top, order, &order.out) 257 poptemp(top, order) 258 } 259 260 // Orderstmtlist orders each of the statements in the list. 261 func orderstmtlist(l Nodes, order *Order) { 262 for _, n := range l.Slice() { 263 orderstmt(n, order) 264 } 265 } 266 267 // Orderblock orders the block of statements l onto a new list, 268 // and returns the ordered list. 269 func orderblock(l Nodes) []*Node { 270 var order Order 271 mark := marktemp(&order) 272 orderstmtlist(l, &order) 273 cleantemp(mark, &order) 274 return order.out 275 } 276 277 // OrderblockNodes orders the block of statements in n into a new slice, 278 // and then replaces the old slice in n with the new slice. 279 func orderblockNodes(n *Nodes) { 280 var order Order 281 mark := marktemp(&order) 282 orderstmtlist(*n, &order) 283 cleantemp(mark, &order) 284 n.Set(order.out) 285 } 286 287 // Orderexprinplace orders the side effects in *np and 288 // leaves them as the init list of the final *np. 289 // The result of orderexprinplace MUST be assigned back to n, e.g. 290 // n.Left = orderexprinplace(n.Left, outer) 291 func orderexprinplace(n *Node, outer *Order) *Node { 292 var order Order 293 n = orderexpr(n, &order, nil) 294 n = addinit(n, order.out) 295 296 // insert new temporaries from order 297 // at head of outer list. 298 outer.temp = append(outer.temp, order.temp...) 299 return n 300 } 301 302 // Orderstmtinplace orders the side effects of the single statement *np 303 // and replaces it with the resulting statement list. 304 // The result of orderstmtinplace MUST be assigned back to n, e.g. 305 // n.Left = orderstmtinplace(n.Left) 306 func orderstmtinplace(n *Node) *Node { 307 var order Order 308 mark := marktemp(&order) 309 orderstmt(n, &order) 310 cleantemp(mark, &order) 311 return liststmt(order.out) 312 } 313 314 // Orderinit moves n's init list to order->out. 315 func orderinit(n *Node, order *Order) { 316 if n.mayBeShared() { 317 // For concurrency safety, don't mutate potentially shared nodes. 318 // First, ensure that no work is required here. 319 if n.Ninit.Len() > 0 { 320 Fatalf("orderinit shared node with ninit") 321 } 322 return 323 } 324 orderstmtlist(n.Ninit, order) 325 n.Ninit.Set(nil) 326 } 327 328 // Ismulticall reports whether the list l is f() for a multi-value function. 329 // Such an f() could appear as the lone argument to a multi-arg function. 330 func ismulticall(l Nodes) bool { 331 // one arg only 332 if l.Len() != 1 { 333 return false 334 } 335 n := l.First() 336 337 // must be call 338 switch n.Op { 339 default: 340 return false 341 342 case OCALLFUNC, OCALLMETH, OCALLINTER: 343 break 344 } 345 346 // call must return multiple values 347 return n.Left.Type.NumResults() > 1 348 } 349 350 // Copyret emits t1, t2, ... = n, where n is a function call, 351 // and then returns the list t1, t2, .... 352 func copyret(n *Node, order *Order) []*Node { 353 if !n.Type.IsFuncArgStruct() { 354 Fatalf("copyret %v %d", n.Type, n.Left.Type.NumResults()) 355 } 356 357 var l1 []*Node 358 var l2 []*Node 359 for _, t := range n.Type.Fields().Slice() { 360 tmp := temp(t.Type) 361 l1 = append(l1, tmp) 362 l2 = append(l2, tmp) 363 } 364 365 as := nod(OAS2, nil, nil) 366 as.List.Set(l1) 367 as.Rlist.Set1(n) 368 as = typecheck(as, Etop) 369 orderstmt(as, order) 370 371 return l2 372 } 373 374 // Ordercallargs orders the list of call arguments *l. 375 func ordercallargs(l *Nodes, order *Order) { 376 if ismulticall(*l) { 377 // return f() where f() is multiple values. 378 l.Set(copyret(l.First(), order)) 379 } else { 380 orderexprlist(*l, order) 381 } 382 } 383 384 // Ordercall orders the call expression n. 385 // n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY. 386 func ordercall(n *Node, order *Order) { 387 n.Left = orderexpr(n.Left, order, nil) 388 n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp 389 ordercallargs(&n.List, order) 390 391 if n.Op == OCALLFUNC { 392 keepAlive := func(i int) { 393 // If the argument is really a pointer being converted to uintptr, 394 // arrange for the pointer to be kept alive until the call returns, 395 // by copying it into a temp and marking that temp 396 // still alive when we pop the temp stack. 397 xp := n.List.Addr(i) 398 for (*xp).Op == OCONVNOP && !(*xp).Type.IsPtr() { 399 xp = &(*xp).Left 400 } 401 x := *xp 402 if x.Type.IsPtr() { 403 x = ordercopyexpr(x, x.Type, order, 0) 404 x.Name.SetKeepalive(true) 405 *xp = x 406 } 407 } 408 409 for i, t := range n.Left.Type.Params().FieldSlice() { 410 // Check for "unsafe-uintptr" tag provided by escape analysis. 411 if t.Isddd() && !n.Isddd() { 412 if t.Note == uintptrEscapesTag { 413 for ; i < n.List.Len(); i++ { 414 keepAlive(i) 415 } 416 } 417 } else { 418 if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag { 419 keepAlive(i) 420 } 421 } 422 } 423 } 424 } 425 426 // Ordermapassign appends n to order->out, introducing temporaries 427 // to make sure that all map assignments have the form m[k] = x. 428 // (Note: orderexpr has already been called on n, so we know k is addressable.) 429 // 430 // If n is the multiple assignment form ..., m[k], ... = ..., 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 order.out = append(order.out, n) 448 449 case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC: 450 var post []*Node 451 for i, m := range n.List.Slice() { 452 switch { 453 case m.Op == OINDEXMAP: 454 if !m.Left.IsAutoTmp() { 455 m.Left = ordercopyexpr(m.Left, m.Left.Type, order, 0) 456 } 457 if !m.Right.IsAutoTmp() { 458 m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0) 459 } 460 fallthrough 461 case instrumenting && n.Op == OAS2FUNC && !isblank(m): 462 t := ordertemp(m.Type, order, false) 463 n.List.SetIndex(i, t) 464 a := nod(OAS, m, t) 465 a = typecheck(a, Etop) 466 post = append(post, a) 467 } 468 } 469 470 order.out = append(order.out, n) 471 order.out = append(order.out, post...) 472 } 473 } 474 475 // Orderstmt orders the statement n, appending to order->out. 476 // Temporaries created during the statement are cleaned 477 // up using VARKILL instructions as possible. 478 func orderstmt(n *Node, order *Order) { 479 if n == nil { 480 return 481 } 482 483 lno := setlineno(n) 484 485 orderinit(n, order) 486 487 switch n.Op { 488 default: 489 Fatalf("orderstmt %v", n.Op) 490 491 case OVARKILL, OVARLIVE: 492 order.out = append(order.out, n) 493 494 case OAS: 495 t := marktemp(order) 496 n.Left = orderexpr(n.Left, order, nil) 497 n.Right = orderexpr(n.Right, order, n.Left) 498 ordermapassign(n, order) 499 cleantemp(t, order) 500 501 case OAS2, 502 OCLOSE, 503 OCOPY, 504 OPRINT, 505 OPRINTN, 506 ORECOVER, 507 ORECV: 508 t := marktemp(order) 509 n.Left = orderexpr(n.Left, order, nil) 510 n.Right = orderexpr(n.Right, order, nil) 511 orderexprlist(n.List, order) 512 orderexprlist(n.Rlist, order) 513 switch n.Op { 514 case OAS2: 515 ordermapassign(n, order) 516 default: 517 order.out = append(order.out, n) 518 } 519 cleantemp(t, order) 520 521 case OASOP: 522 // Special: rewrite l op= r into l = l op r. 523 // This simplifies quite a few operations; 524 // most important is that it lets us separate 525 // out map read from map write when l is 526 // a map index expression. 527 t := marktemp(order) 528 n.Left = orderexpr(n.Left, order, nil) 529 n.Right = orderexpr(n.Right, order, nil) 530 531 n.Left = ordersafeexpr(n.Left, order) 532 tmp1 := treecopy(n.Left, src.NoXPos) 533 if tmp1.Op == OINDEXMAP { 534 tmp1.Etype = 0 // now an rvalue not an lvalue 535 } 536 tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0) 537 // TODO(marvin): Fix Node.EType type union. 538 n.Right = nod(Op(n.Etype), tmp1, n.Right) 539 n.Right = typecheck(n.Right, Erv) 540 n.Right = orderexpr(n.Right, order, nil) 541 n.Etype = 0 542 n.Op = OAS 543 ordermapassign(n, order) 544 cleantemp(t, order) 545 546 // Special: make sure key is addressable if needed, 547 // and make sure OINDEXMAP is not copied out. 548 case OAS2MAPR: 549 t := marktemp(order) 550 551 orderexprlist(n.List, order) 552 r := n.Rlist.First() 553 r.Left = orderexpr(r.Left, order, nil) 554 r.Right = orderexpr(r.Right, order, nil) 555 556 // See case OINDEXMAP below. 557 if r.Right.Op == OARRAYBYTESTR { 558 r.Right.Op = OARRAYBYTESTRTMP 559 } 560 r.Right = ordermapkeytemp(r.Left.Type, r.Right, order) 561 orderokas2(n, order) 562 cleantemp(t, order) 563 564 // Special: avoid copy of func call n->rlist->n. 565 case OAS2FUNC: 566 t := marktemp(order) 567 568 orderexprlist(n.List, order) 569 ordercall(n.Rlist.First(), order) 570 orderas2(n, order) 571 cleantemp(t, order) 572 573 // Special: use temporary variables to hold result, 574 // so that assertI2Tetc can take address of temporary. 575 // No temporary for blank assignment. 576 case OAS2DOTTYPE: 577 t := marktemp(order) 578 579 orderexprlist(n.List, order) 580 n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T) 581 orderokas2(n, order) 582 cleantemp(t, order) 583 584 // Special: use temporary variables to hold result, 585 // so that chanrecv can take address of temporary. 586 case OAS2RECV: 587 t := marktemp(order) 588 589 orderexprlist(n.List, order) 590 n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv 591 ch := n.Rlist.First().Left.Type 592 tmp1 := ordertemp(ch.Elem(), order, types.Haspointers(ch.Elem())) 593 tmp2 := ordertemp(types.Types[TBOOL], order, false) 594 order.out = append(order.out, n) 595 r := nod(OAS, n.List.First(), tmp1) 596 r = typecheck(r, Etop) 597 ordermapassign(r, order) 598 r = okas(n.List.Second(), tmp2) 599 r = typecheck(r, Etop) 600 ordermapassign(r, order) 601 n.List.Set2(tmp1, tmp2) 602 cleantemp(t, order) 603 604 // Special: does not save n onto out. 605 case OBLOCK, OEMPTY: 606 orderstmtlist(n.List, order) 607 608 // Special: n->left is not an expression; save as is. 609 case OBREAK, 610 OCONTINUE, 611 ODCL, 612 ODCLCONST, 613 ODCLTYPE, 614 OFALL, 615 OGOTO, 616 OLABEL, 617 ORETJMP: 618 order.out = append(order.out, n) 619 620 // Special: handle call arguments. 621 case OCALLFUNC, OCALLINTER, OCALLMETH: 622 t := marktemp(order) 623 624 ordercall(n, order) 625 order.out = append(order.out, n) 626 cleantemp(t, order) 627 628 // Special: order arguments to inner call but not call itself. 629 case ODEFER, OPROC: 630 t := marktemp(order) 631 632 switch n.Left.Op { 633 // Delete will take the address of the key. 634 // Copy key into new temp and do not clean it 635 // (it persists beyond the statement). 636 case ODELETE: 637 orderexprlist(n.Left.List, order) 638 639 if mapfast(n.Left.List.First().Type) == mapslow { 640 t1 := marktemp(order) 641 np := n.Left.List.Addr(1) // map key 642 *np = ordercopyexpr(*np, (*np).Type, order, 0) 643 poptemp(t1, order) 644 } 645 646 default: 647 ordercall(n.Left, order) 648 } 649 650 order.out = append(order.out, n) 651 cleantemp(t, order) 652 653 case ODELETE: 654 t := marktemp(order) 655 n.List.SetFirst(orderexpr(n.List.First(), order, nil)) 656 n.List.SetSecond(orderexpr(n.List.Second(), order, nil)) 657 n.List.SetSecond(ordermapkeytemp(n.List.First().Type, n.List.Second(), order)) 658 order.out = append(order.out, n) 659 cleantemp(t, order) 660 661 // Clean temporaries from condition evaluation at 662 // beginning of loop body and after for statement. 663 case OFOR: 664 t := marktemp(order) 665 666 n.Left = orderexprinplace(n.Left, order) 667 var l []*Node 668 cleantempnopop(t, order, &l) 669 n.Nbody.Prepend(l...) 670 orderblockNodes(&n.Nbody) 671 n.Right = orderstmtinplace(n.Right) 672 order.out = append(order.out, n) 673 cleantemp(t, order) 674 675 // Clean temporaries from condition at 676 // beginning of both branches. 677 case OIF: 678 t := marktemp(order) 679 680 n.Left = orderexprinplace(n.Left, order) 681 var l []*Node 682 cleantempnopop(t, order, &l) 683 n.Nbody.Prepend(l...) 684 l = nil 685 cleantempnopop(t, order, &l) 686 n.Rlist.Prepend(l...) 687 poptemp(t, order) 688 orderblockNodes(&n.Nbody) 689 n.Rlist.Set(orderblock(n.Rlist)) 690 order.out = append(order.out, n) 691 692 // Special: argument will be converted to interface using convT2E 693 // so make sure it is an addressable temporary. 694 case OPANIC: 695 t := marktemp(order) 696 697 n.Left = orderexpr(n.Left, order, nil) 698 if !n.Left.Type.IsInterface() { 699 n.Left = orderaddrtemp(n.Left, order) 700 } 701 order.out = append(order.out, n) 702 cleantemp(t, order) 703 704 case ORANGE: 705 // n.Right is the expression being ranged over. 706 // order it, and then make a copy if we need one. 707 // We almost always do, to ensure that we don't 708 // see any value changes made during the loop. 709 // Usually the copy is cheap (e.g., array pointer, 710 // chan, slice, string are all tiny). 711 // The exception is ranging over an array value 712 // (not a slice, not a pointer to array), 713 // which must make a copy to avoid seeing updates made during 714 // the range body. Ranging over an array value is uncommon though. 715 716 // Mark []byte(str) range expression to reuse string backing storage. 717 // It is safe because the storage cannot be mutated. 718 if n.Right.Op == OSTRARRAYBYTE { 719 n.Right.Op = OSTRARRAYBYTETMP 720 } 721 722 t := marktemp(order) 723 n.Right = orderexpr(n.Right, order, nil) 724 switch n.Type.Etype { 725 default: 726 Fatalf("orderstmt range %v", n.Type) 727 728 case TARRAY, TSLICE: 729 if n.List.Len() < 2 || isblank(n.List.Second()) { 730 // for i := range x will only use x once, to compute len(x). 731 // No need to copy it. 732 break 733 } 734 fallthrough 735 736 case TCHAN, TSTRING: 737 // chan, string, slice, array ranges use value multiple times. 738 // make copy. 739 r := n.Right 740 741 if r.Type.IsString() && r.Type != types.Types[TSTRING] { 742 r = nod(OCONV, r, nil) 743 r.Type = types.Types[TSTRING] 744 r = typecheck(r, Erv) 745 } 746 747 n.Right = ordercopyexpr(r, r.Type, order, 0) 748 749 case TMAP: 750 // copy the map value in case it is a map literal. 751 // TODO(rsc): Make tmp = literal expressions reuse tmp. 752 // For maps tmp is just one word so it hardly matters. 753 r := n.Right 754 n.Right = ordercopyexpr(r, r.Type, order, 0) 755 756 // prealloc[n] is the temp for the iterator. 757 // hiter contains pointers and needs to be zeroed. 758 prealloc[n] = ordertemp(hiter(n.Type), order, true) 759 } 760 for i, n1 := range n.List.Slice() { 761 n.List.SetIndex(i, orderexprinplace(n1, order)) 762 } 763 orderblockNodes(&n.Nbody) 764 order.out = append(order.out, n) 765 cleantemp(t, order) 766 767 case ORETURN: 768 ordercallargs(&n.List, order) 769 order.out = append(order.out, n) 770 771 // Special: clean case temporaries in each block entry. 772 // Select must enter one of its blocks, so there is no 773 // need for a cleaning at the end. 774 // Doubly special: evaluation order for select is stricter 775 // than ordinary expressions. Even something like p.c 776 // has to be hoisted into a temporary, so that it cannot be 777 // reordered after the channel evaluation for a different 778 // case (if p were nil, then the timing of the fault would 779 // give this away). 780 case OSELECT: 781 t := marktemp(order) 782 783 for _, n2 := range n.List.Slice() { 784 if n2.Op != OXCASE { 785 Fatalf("order select case %v", n2.Op) 786 } 787 r := n2.Left 788 setlineno(n2) 789 790 // Append any new body prologue to ninit. 791 // The next loop will insert ninit into nbody. 792 if n2.Ninit.Len() != 0 { 793 Fatalf("order select ninit") 794 } 795 if r != nil { 796 switch r.Op { 797 default: 798 Dump("select case", r) 799 Fatalf("unknown op in select %v", r.Op) 800 801 // If this is case x := <-ch or case x, y := <-ch, the case has 802 // the ODCL nodes to declare x and y. We want to delay that 803 // declaration (and possible allocation) until inside the case body. 804 // Delete the ODCL nodes here and recreate them inside the body below. 805 case OSELRECV, OSELRECV2: 806 if r.Colas() { 807 i := 0 808 if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left { 809 i++ 810 } 811 if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() { 812 i++ 813 } 814 if i >= r.Ninit.Len() { 815 r.Ninit.Set(nil) 816 } 817 } 818 819 if r.Ninit.Len() != 0 { 820 dumplist("ninit", r.Ninit) 821 Fatalf("ninit on select recv") 822 } 823 824 // case x = <-c 825 // case x, ok = <-c 826 // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c. 827 // r->left == N means 'case <-c'. 828 // c is always evaluated; x and ok are only evaluated when assigned. 829 r.Right.Left = orderexpr(r.Right.Left, order, nil) 830 831 if r.Right.Left.Op != ONAME { 832 r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0) 833 } 834 835 // Introduce temporary for receive and move actual copy into case body. 836 // avoids problems with target being addressed, as usual. 837 // NOTE: If we wanted to be clever, we could arrange for just one 838 // temporary per distinct type, sharing the temp among all receives 839 // with that temp. Similarly one ok bool could be shared among all 840 // the x,ok receives. Not worth doing until there's a clear need. 841 if r.Left != nil && isblank(r.Left) { 842 r.Left = nil 843 } 844 if r.Left != nil { 845 // use channel element type for temporary to avoid conversions, 846 // such as in case interfacevalue = <-intchan. 847 // the conversion happens in the OAS instead. 848 tmp1 := r.Left 849 850 if r.Colas() { 851 tmp2 := nod(ODCL, tmp1, nil) 852 tmp2 = typecheck(tmp2, Etop) 853 n2.Ninit.Append(tmp2) 854 } 855 856 r.Left = ordertemp(r.Right.Left.Type.Elem(), order, types.Haspointers(r.Right.Left.Type.Elem())) 857 tmp2 := nod(OAS, tmp1, r.Left) 858 tmp2 = typecheck(tmp2, Etop) 859 n2.Ninit.Append(tmp2) 860 } 861 862 if r.List.Len() != 0 && isblank(r.List.First()) { 863 r.List.Set(nil) 864 } 865 if r.List.Len() != 0 { 866 tmp1 := r.List.First() 867 if r.Colas() { 868 tmp2 := nod(ODCL, tmp1, nil) 869 tmp2 = typecheck(tmp2, Etop) 870 n2.Ninit.Append(tmp2) 871 } 872 873 r.List.Set1(ordertemp(types.Types[TBOOL], order, false)) 874 tmp2 := okas(tmp1, r.List.First()) 875 tmp2 = typecheck(tmp2, Etop) 876 n2.Ninit.Append(tmp2) 877 } 878 n2.Ninit.Set(orderblock(n2.Ninit)) 879 880 case OSEND: 881 if r.Ninit.Len() != 0 { 882 dumplist("ninit", r.Ninit) 883 Fatalf("ninit on select send") 884 } 885 886 // case c <- x 887 // r->left is c, r->right is x, both are always evaluated. 888 r.Left = orderexpr(r.Left, order, nil) 889 890 if !r.Left.IsAutoTmp() { 891 r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0) 892 } 893 r.Right = orderexpr(r.Right, order, nil) 894 if !r.Right.IsAutoTmp() { 895 r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0) 896 } 897 } 898 } 899 900 orderblockNodes(&n2.Nbody) 901 } 902 // Now that we have accumulated all the temporaries, clean them. 903 // Also insert any ninit queued during the previous loop. 904 // (The temporary cleaning must follow that ninit work.) 905 for _, n3 := range n.List.Slice() { 906 s := n3.Ninit.Slice() 907 cleantempnopop(t, order, &s) 908 n3.Nbody.Prepend(s...) 909 n3.Ninit.Set(nil) 910 } 911 912 order.out = append(order.out, n) 913 poptemp(t, order) 914 915 // Special: value being sent is passed as a pointer; make it addressable. 916 case OSEND: 917 t := marktemp(order) 918 919 n.Left = orderexpr(n.Left, order, nil) 920 n.Right = orderexpr(n.Right, order, nil) 921 if instrumenting { 922 // Force copying to the stack so that (chan T)(nil) <- x 923 // is still instrumented as a read of x. 924 n.Right = ordercopyexpr(n.Right, n.Right.Type, order, 0) 925 } else { 926 n.Right = orderaddrtemp(n.Right, order) 927 } 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 := types.NewArray(types.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 n.Right = ordermapkeytemp(n.Left.Type, n.Right, order) 1075 if needCopy { 1076 n = ordercopyexpr(n, n.Type, order, 0) 1077 } 1078 1079 // concrete type (not interface) argument must be addressable 1080 // temporary to pass to runtime. 1081 case OCONVIFACE: 1082 n.Left = orderexpr(n.Left, order, nil) 1083 1084 if !n.Left.Type.IsInterface() { 1085 n.Left = orderaddrtemp(n.Left, order) 1086 } 1087 1088 case OCONVNOP: 1089 if n.Type.IsKind(TUNSAFEPTR) && n.Left.Type.IsKind(TUINTPTR) && (n.Left.Op == OCALLFUNC || n.Left.Op == OCALLINTER || n.Left.Op == OCALLMETH) { 1090 // When reordering unsafe.Pointer(f()) into a separate 1091 // statement, the conversion and function call must stay 1092 // together. See golang.org/issue/15329. 1093 orderinit(n.Left, order) 1094 ordercall(n.Left, order) 1095 if lhs == nil || lhs.Op != ONAME || instrumenting { 1096 n = ordercopyexpr(n, n.Type, order, 0) 1097 } 1098 } else { 1099 n.Left = orderexpr(n.Left, order, nil) 1100 } 1101 1102 case OANDAND, OOROR: 1103 mark := marktemp(order) 1104 n.Left = orderexpr(n.Left, order, nil) 1105 1106 // Clean temporaries from first branch at beginning of second. 1107 // Leave them on the stack so that they can be killed in the outer 1108 // context in case the short circuit is taken. 1109 var s []*Node 1110 1111 cleantempnopop(mark, order, &s) 1112 n.Right = addinit(n.Right, s) 1113 n.Right = orderexprinplace(n.Right, order) 1114 1115 case OCALLFUNC, 1116 OCALLINTER, 1117 OCALLMETH, 1118 OCAP, 1119 OCOMPLEX, 1120 OCOPY, 1121 OIMAG, 1122 OLEN, 1123 OMAKECHAN, 1124 OMAKEMAP, 1125 OMAKESLICE, 1126 ONEW, 1127 OREAL, 1128 ORECOVER, 1129 OSTRARRAYBYTE, 1130 OSTRARRAYBYTETMP, 1131 OSTRARRAYRUNE: 1132 ordercall(n, order) 1133 if lhs == nil || lhs.Op != ONAME || instrumenting { 1134 n = ordercopyexpr(n, n.Type, order, 0) 1135 } 1136 1137 case OAPPEND: 1138 ordercallargs(&n.List, order) 1139 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) { 1140 n = ordercopyexpr(n, n.Type, order, 0) 1141 } 1142 1143 case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: 1144 n.Left = orderexpr(n.Left, order, nil) 1145 low, high, max := n.SliceBounds() 1146 low = orderexpr(low, order, nil) 1147 low = ordercheapexpr(low, order) 1148 high = orderexpr(high, order, nil) 1149 high = ordercheapexpr(high, order) 1150 max = orderexpr(max, order, nil) 1151 max = ordercheapexpr(max, order) 1152 n.SetSliceBounds(low, high, max) 1153 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { 1154 n = ordercopyexpr(n, n.Type, order, 0) 1155 } 1156 1157 case OCLOSURE: 1158 if n.Noescape() && n.Func.Cvars.Len() > 0 { 1159 prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type 1160 } 1161 1162 case OARRAYLIT, OSLICELIT, OCALLPART: 1163 n.Left = orderexpr(n.Left, order, nil) 1164 n.Right = orderexpr(n.Right, order, nil) 1165 orderexprlist(n.List, order) 1166 orderexprlist(n.Rlist, order) 1167 if n.Noescape() { 1168 prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type 1169 } 1170 1171 case ODDDARG: 1172 if n.Noescape() { 1173 // The ddd argument does not live beyond the call it is created for. 1174 // Allocate a temporary that will be cleaned up when this statement 1175 // completes. We could be more aggressive and try to arrange for it 1176 // to be cleaned up when the call completes. 1177 prealloc[n] = ordertemp(n.Type.Elem(), order, false) 1178 } 1179 1180 case ODOTTYPE, ODOTTYPE2: 1181 n.Left = orderexpr(n.Left, order, nil) 1182 // TODO(rsc): The isfat is for consistency with componentgen and walkexpr. 1183 // It needs to be removed in all three places. 1184 // That would allow inlining x.(struct{*int}) the same as x.(*int). 1185 if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting { 1186 n = ordercopyexpr(n, n.Type, order, 1) 1187 } 1188 1189 case ORECV: 1190 n.Left = orderexpr(n.Left, order, nil) 1191 n = ordercopyexpr(n, n.Type, order, 1) 1192 1193 case OEQ, ONE: 1194 n.Left = orderexpr(n.Left, order, nil) 1195 n.Right = orderexpr(n.Right, order, nil) 1196 t := n.Left.Type 1197 if t.IsStruct() || t.IsArray() { 1198 // for complex comparisons, we need both args to be 1199 // addressable so we can pass them to the runtime. 1200 n.Left = orderaddrtemp(n.Left, order) 1201 n.Right = orderaddrtemp(n.Right, order) 1202 } 1203 } 1204 1205 lineno = lno 1206 return n 1207 } 1208 1209 // okas creates and returns an assignment of val to ok, 1210 // including an explicit conversion if necessary. 1211 func okas(ok, val *Node) *Node { 1212 if !isblank(ok) { 1213 val = conv(val, ok.Type) 1214 } 1215 return nod(OAS, ok, val) 1216 } 1217 1218 // orderas2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment. 1219 // The caller should order the right-hand side of the assignment before calling orderas2. 1220 // It rewrites, 1221 // a, b, a = ... 1222 // as 1223 // tmp1, tmp2, tmp3 = ... 1224 // a, b, a = tmp1, tmp2, tmp3 1225 // This is necessary to ensure left to right assignment order. 1226 func orderas2(n *Node, order *Order) { 1227 tmplist := []*Node{} 1228 left := []*Node{} 1229 for _, l := range n.List.Slice() { 1230 if !isblank(l) { 1231 tmp := ordertemp(l.Type, order, types.Haspointers(l.Type)) 1232 tmplist = append(tmplist, tmp) 1233 left = append(left, l) 1234 } 1235 } 1236 1237 order.out = append(order.out, n) 1238 1239 as := nod(OAS2, nil, nil) 1240 as.List.Set(left) 1241 as.Rlist.Set(tmplist) 1242 as = typecheck(as, Etop) 1243 orderstmt(as, order) 1244 1245 ti := 0 1246 for ni, l := range n.List.Slice() { 1247 if !isblank(l) { 1248 n.List.SetIndex(ni, tmplist[ti]) 1249 ti++ 1250 } 1251 } 1252 } 1253 1254 // orderokas2 orders OAS2 with ok. 1255 // Just like orderas2(), this also adds temporaries to ensure left-to-right assignment. 1256 func orderokas2(n *Node, order *Order) { 1257 var tmp1, tmp2 *Node 1258 if !isblank(n.List.First()) { 1259 typ := n.Rlist.First().Type 1260 tmp1 = ordertemp(typ, order, types.Haspointers(typ)) 1261 } 1262 1263 if !isblank(n.List.Second()) { 1264 tmp2 = ordertemp(types.Types[TBOOL], order, false) 1265 } 1266 1267 order.out = append(order.out, n) 1268 1269 if tmp1 != nil { 1270 r := nod(OAS, n.List.First(), tmp1) 1271 r = typecheck(r, Etop) 1272 ordermapassign(r, order) 1273 n.List.SetFirst(tmp1) 1274 } 1275 if tmp2 != nil { 1276 r := okas(n.List.Second(), tmp2) 1277 r = typecheck(r, Etop) 1278 ordermapassign(r, order) 1279 n.List.SetSecond(tmp2) 1280 } 1281 }