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