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