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