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