github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/gc/walk.c (about) 1 // Copyright 2009 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 #include <u.h> 6 #include <libc.h> 7 #include "go.h" 8 9 static Node* walkprint(Node*, NodeList**, int); 10 static Node* mapfn(char*, Type*); 11 static Node* mapfndel(char*, Type*); 12 static Node* ascompatee1(int, Node*, Node*, NodeList**); 13 static NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**); 14 static NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**); 15 static NodeList* ascompatte(int, Node*, int, Type**, NodeList*, int, NodeList**); 16 static Node* convas(Node*, NodeList**); 17 static void heapmoves(void); 18 static NodeList* paramstoheap(Type **argin, int out); 19 static NodeList* reorder1(NodeList*); 20 static NodeList* reorder3(NodeList*); 21 static Node* addstr(Node*, NodeList**); 22 static Node* appendslice(Node*, NodeList**); 23 static Node* append(Node*, NodeList**); 24 static Node* copyany(Node*, NodeList**, int); 25 static Node* sliceany(Node*, NodeList**); 26 static void walkcompare(Node**, NodeList**); 27 static void walkrotate(Node**); 28 static void walkmul(Node**, NodeList**); 29 static void walkdiv(Node**, NodeList**); 30 static int bounded(Node*, int64); 31 static Mpint mpzero; 32 33 void 34 walk(Node *fn) 35 { 36 char s[50]; 37 NodeList *l; 38 int lno; 39 40 curfn = fn; 41 42 if(debug['W']) { 43 snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym); 44 dumplist(s, curfn->nbody); 45 } 46 47 lno = lineno; 48 49 // Final typecheck for any unused variables. 50 // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below. 51 for(l=fn->dcl; l; l=l->next) 52 if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO) 53 typecheck(&l->n, Erv | Easgn); 54 55 // Propagate the used flag for typeswitch variables up to the NONAME in it's definition. 56 for(l=fn->dcl; l; l=l->next) 57 if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO && l->n->defn && l->n->defn->op == OTYPESW && l->n->used) 58 l->n->defn->left->used++; 59 60 for(l=fn->dcl; l; l=l->next) { 61 if(l->n->op != ONAME || (l->n->class&~PHEAP) != PAUTO || l->n->sym->name[0] == '&' || l->n->used) 62 continue; 63 if(l->n->defn && l->n->defn->op == OTYPESW) { 64 if(l->n->defn->left->used) 65 continue; 66 lineno = l->n->defn->left->lineno; 67 yyerror("%S declared and not used", l->n->sym); 68 l->n->defn->left->used = 1; // suppress repeats 69 } else { 70 lineno = l->n->lineno; 71 yyerror("%S declared and not used", l->n->sym); 72 } 73 } 74 75 lineno = lno; 76 if(nerrors != 0) 77 return; 78 walkstmtlist(curfn->nbody); 79 if(debug['W']) { 80 snprint(s, sizeof(s), "after walk %S", curfn->nname->sym); 81 dumplist(s, curfn->nbody); 82 } 83 heapmoves(); 84 if(debug['W'] && curfn->enter != nil) { 85 snprint(s, sizeof(s), "enter %S", curfn->nname->sym); 86 dumplist(s, curfn->enter); 87 } 88 } 89 90 91 void 92 walkstmtlist(NodeList *l) 93 { 94 for(; l; l=l->next) 95 walkstmt(&l->n); 96 } 97 98 static int 99 samelist(NodeList *a, NodeList *b) 100 { 101 for(; a && b; a=a->next, b=b->next) 102 if(a->n != b->n) 103 return 0; 104 return a == b; 105 } 106 107 static int 108 paramoutheap(Node *fn) 109 { 110 NodeList *l; 111 112 for(l=fn->dcl; l; l=l->next) { 113 switch(l->n->class) { 114 case PPARAMOUT: 115 case PPARAMOUT|PHEAP: 116 return l->n->addrtaken; 117 case PAUTO: 118 case PAUTO|PHEAP: 119 // stop early - parameters are over 120 return 0; 121 } 122 } 123 return 0; 124 } 125 126 void 127 walkstmt(Node **np) 128 { 129 NodeList *init; 130 NodeList *ll, *rl; 131 int cl; 132 Node *n, *f; 133 134 n = *np; 135 if(n == N) 136 return; 137 138 setlineno(n); 139 140 walkstmtlist(n->ninit); 141 142 switch(n->op) { 143 default: 144 if(n->op == ONAME) 145 yyerror("%S is not a top level statement", n->sym); 146 else 147 yyerror("%O is not a top level statement", n->op); 148 dump("nottop", n); 149 break; 150 151 case OAS: 152 case OASOP: 153 case OAS2: 154 case OAS2DOTTYPE: 155 case OAS2RECV: 156 case OAS2FUNC: 157 case OAS2MAPR: 158 case OCLOSE: 159 case OCOPY: 160 case OCALLMETH: 161 case OCALLINTER: 162 case OCALL: 163 case OCALLFUNC: 164 case ODELETE: 165 case OSEND: 166 case OPRINT: 167 case OPRINTN: 168 case OPANIC: 169 case OEMPTY: 170 case ORECOVER: 171 if(n->typecheck == 0) 172 fatal("missing typecheck: %+N", n); 173 init = n->ninit; 174 n->ninit = nil; 175 walkexpr(&n, &init); 176 addinit(&n, init); 177 if((*np)->op == OCOPY && n->op == OCONVNOP) 178 n->op = OEMPTY; // don't leave plain values as statements. 179 break; 180 181 case ORECV: 182 // special case for a receive where we throw away 183 // the value received. 184 if(n->typecheck == 0) 185 fatal("missing typecheck: %+N", n); 186 init = n->ninit; 187 n->ninit = nil; 188 189 walkexpr(&n->left, &init); 190 n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, &init, typename(n->left->type), n->left, nodnil()); 191 walkexpr(&n, &init); 192 193 addinit(&n, init); 194 break; 195 196 case OBREAK: 197 case ODCL: 198 case OCONTINUE: 199 case OFALL: 200 case OGOTO: 201 case OLABEL: 202 case ODCLCONST: 203 case ODCLTYPE: 204 case OCHECKNIL: 205 case OVARKILL: 206 break; 207 208 case OBLOCK: 209 walkstmtlist(n->list); 210 break; 211 212 case OXCASE: 213 yyerror("case statement out of place"); 214 n->op = OCASE; 215 case OCASE: 216 walkstmt(&n->right); 217 break; 218 219 case ODEFER: 220 hasdefer = 1; 221 switch(n->left->op) { 222 case OPRINT: 223 case OPRINTN: 224 walkexprlist(n->left->list, &n->ninit); 225 n->left = walkprint(n->left, &n->ninit, 1); 226 break; 227 case OCOPY: 228 n->left = copyany(n->left, &n->ninit, 1); 229 break; 230 default: 231 walkexpr(&n->left, &n->ninit); 232 break; 233 } 234 break; 235 236 case OFOR: 237 if(n->ntest != N) { 238 walkstmtlist(n->ntest->ninit); 239 init = n->ntest->ninit; 240 n->ntest->ninit = nil; 241 walkexpr(&n->ntest, &init); 242 addinit(&n->ntest, init); 243 } 244 walkstmt(&n->nincr); 245 walkstmtlist(n->nbody); 246 break; 247 248 case OIF: 249 walkexpr(&n->ntest, &n->ninit); 250 walkstmtlist(n->nbody); 251 walkstmtlist(n->nelse); 252 break; 253 254 case OPROC: 255 switch(n->left->op) { 256 case OPRINT: 257 case OPRINTN: 258 walkexprlist(n->left->list, &n->ninit); 259 n->left = walkprint(n->left, &n->ninit, 1); 260 break; 261 case OCOPY: 262 n->left = copyany(n->left, &n->ninit, 1); 263 break; 264 default: 265 walkexpr(&n->left, &n->ninit); 266 break; 267 } 268 break; 269 270 case ORETURN: 271 walkexprlist(n->list, &n->ninit); 272 if(n->list == nil) 273 break; 274 if((curfn->type->outnamed && count(n->list) > 1) || paramoutheap(curfn)) { 275 // assign to the function out parameters, 276 // so that reorder3 can fix up conflicts 277 rl = nil; 278 for(ll=curfn->dcl; ll != nil; ll=ll->next) { 279 cl = ll->n->class & ~PHEAP; 280 if(cl == PAUTO) 281 break; 282 if(cl == PPARAMOUT) 283 rl = list(rl, ll->n); 284 } 285 if(samelist(rl, n->list)) { 286 // special return in disguise 287 n->list = nil; 288 break; 289 } 290 if(count(n->list) == 1 && count(rl) > 1) { 291 // OAS2FUNC in disguise 292 f = n->list->n; 293 if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER) 294 fatal("expected return of call, have %N", f); 295 n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit)); 296 break; 297 } 298 299 // move function calls out, to make reorder3's job easier. 300 walkexprlistsafe(n->list, &n->ninit); 301 ll = ascompatee(n->op, rl, n->list, &n->ninit); 302 n->list = reorder3(ll); 303 break; 304 } 305 ll = ascompatte(n->op, nil, 0, getoutarg(curfn->type), n->list, 1, &n->ninit); 306 n->list = ll; 307 break; 308 309 case ORETJMP: 310 break; 311 312 case OSELECT: 313 walkselect(n); 314 break; 315 316 case OSWITCH: 317 walkswitch(n); 318 break; 319 320 case ORANGE: 321 walkrange(n); 322 break; 323 324 case OXFALL: 325 yyerror("fallthrough statement out of place"); 326 n->op = OFALL; 327 break; 328 } 329 330 if(n->op == ONAME) 331 fatal("walkstmt ended up with name: %+N", n); 332 333 *np = n; 334 } 335 336 337 /* 338 * walk the whole tree of the body of an 339 * expression or simple statement. 340 * the types expressions are calculated. 341 * compile-time constants are evaluated. 342 * complex side effects like statements are appended to init 343 */ 344 345 void 346 walkexprlist(NodeList *l, NodeList **init) 347 { 348 for(; l; l=l->next) 349 walkexpr(&l->n, init); 350 } 351 352 void 353 walkexprlistsafe(NodeList *l, NodeList **init) 354 { 355 for(; l; l=l->next) { 356 l->n = safeexpr(l->n, init); 357 walkexpr(&l->n, init); 358 } 359 } 360 361 void 362 walkexpr(Node **np, NodeList **init) 363 { 364 Node *r, *l, *var, *a; 365 Node *map, *key; 366 NodeList *ll, *lr; 367 Type *t; 368 int et, old_safemode; 369 int64 v; 370 int32 lno; 371 Node *n, *fn, *n1, *n2; 372 Sym *sym; 373 char buf[100], *p; 374 375 n = *np; 376 377 if(n == N) 378 return; 379 380 if(init == &n->ninit) { 381 // not okay to use n->ninit when walking n, 382 // because we might replace n with some other node 383 // and would lose the init list. 384 fatal("walkexpr init == &n->ninit"); 385 } 386 387 if(n->ninit != nil) { 388 walkstmtlist(n->ninit); 389 *init = concat(*init, n->ninit); 390 n->ninit = nil; 391 } 392 393 // annoying case - not typechecked 394 if(n->op == OKEY) { 395 walkexpr(&n->left, init); 396 walkexpr(&n->right, init); 397 return; 398 } 399 400 lno = setlineno(n); 401 402 if(debug['w'] > 1) 403 dump("walk-before", n); 404 405 if(n->typecheck != 1) 406 fatal("missed typecheck: %+N\n", n); 407 408 switch(n->op) { 409 default: 410 dump("walk", n); 411 fatal("walkexpr: switch 1 unknown op %+hN", n); 412 break; 413 414 case OTYPE: 415 case ONONAME: 416 case OINDREG: 417 case OEMPTY: 418 goto ret; 419 420 case ONOT: 421 case OMINUS: 422 case OPLUS: 423 case OCOM: 424 case OREAL: 425 case OIMAG: 426 case ODOTMETH: 427 case ODOTINTER: 428 walkexpr(&n->left, init); 429 goto ret; 430 431 case OIND: 432 walkexpr(&n->left, init); 433 goto ret; 434 435 case ODOT: 436 usefield(n); 437 walkexpr(&n->left, init); 438 goto ret; 439 440 case ODOTPTR: 441 usefield(n); 442 if(n->op == ODOTPTR && n->left->type->type->width == 0) { 443 // No actual copy will be generated, so emit an explicit nil check. 444 n->left = cheapexpr(n->left, init); 445 checknil(n->left, init); 446 } 447 walkexpr(&n->left, init); 448 goto ret; 449 450 case OEFACE: 451 walkexpr(&n->left, init); 452 walkexpr(&n->right, init); 453 goto ret; 454 455 case OSPTR: 456 case OITAB: 457 walkexpr(&n->left, init); 458 goto ret; 459 460 case OLEN: 461 case OCAP: 462 walkexpr(&n->left, init); 463 464 // replace len(*[10]int) with 10. 465 // delayed until now to preserve side effects. 466 t = n->left->type; 467 if(isptr[t->etype]) 468 t = t->type; 469 if(isfixedarray(t)) { 470 safeexpr(n->left, init); 471 nodconst(n, n->type, t->bound); 472 n->typecheck = 1; 473 } 474 goto ret; 475 476 case OLSH: 477 case ORSH: 478 walkexpr(&n->left, init); 479 walkexpr(&n->right, init); 480 t = n->left->type; 481 n->bounded = bounded(n->right, 8*t->width); 482 if(debug['m'] && n->etype && !isconst(n->right, CTINT)) 483 warn("shift bounds check elided"); 484 goto ret; 485 486 case OAND: 487 case OSUB: 488 case OHMUL: 489 case OLT: 490 case OLE: 491 case OGE: 492 case OGT: 493 case OADD: 494 case OCOMPLEX: 495 case OLROT: 496 // Use results from call expression as arguments for complex. 497 if(n->op == OCOMPLEX && n->left == N && n->right == N) { 498 n->left = n->list->n; 499 n->right = n->list->next->n; 500 } 501 walkexpr(&n->left, init); 502 walkexpr(&n->right, init); 503 goto ret; 504 505 case OOR: 506 case OXOR: 507 walkexpr(&n->left, init); 508 walkexpr(&n->right, init); 509 walkrotate(&n); 510 goto ret; 511 512 case OEQ: 513 case ONE: 514 walkexpr(&n->left, init); 515 walkexpr(&n->right, init); 516 // Disable safemode while compiling this code: the code we 517 // generate internally can refer to unsafe.Pointer. 518 // In this case it can happen if we need to generate an == 519 // for a struct containing a reflect.Value, which itself has 520 // an unexported field of type unsafe.Pointer. 521 old_safemode = safemode; 522 safemode = 0; 523 walkcompare(&n, init); 524 safemode = old_safemode; 525 goto ret; 526 527 case OANDAND: 528 case OOROR: 529 walkexpr(&n->left, init); 530 // cannot put side effects from n->right on init, 531 // because they cannot run before n->left is checked. 532 // save elsewhere and store on the eventual n->right. 533 ll = nil; 534 walkexpr(&n->right, &ll); 535 addinit(&n->right, ll); 536 goto ret; 537 538 case OPRINT: 539 case OPRINTN: 540 walkexprlist(n->list, init); 541 n = walkprint(n, init, 0); 542 goto ret; 543 544 case OPANIC: 545 n = mkcall("panic", T, init, n->left); 546 goto ret; 547 548 case ORECOVER: 549 n = mkcall("recover", n->type, init, nod(OADDR, nodfp, N)); 550 goto ret; 551 552 case OLITERAL: 553 n->addable = 1; 554 goto ret; 555 556 case OCLOSUREVAR: 557 case OCFUNC: 558 n->addable = 1; 559 goto ret; 560 561 case ONAME: 562 if(!(n->class & PHEAP) && n->class != PPARAMREF) 563 n->addable = 1; 564 goto ret; 565 566 case OCALLINTER: 567 t = n->left->type; 568 if(n->list && n->list->n->op == OAS) 569 goto ret; 570 walkexpr(&n->left, init); 571 walkexprlist(n->list, init); 572 ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init); 573 n->list = reorder1(ll); 574 goto ret; 575 576 case OCALLFUNC: 577 t = n->left->type; 578 if(n->list && n->list->n->op == OAS) 579 goto ret; 580 581 walkexpr(&n->left, init); 582 walkexprlist(n->list, init); 583 584 ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init); 585 n->list = reorder1(ll); 586 goto ret; 587 588 case OCALLMETH: 589 t = n->left->type; 590 if(n->list && n->list->n->op == OAS) 591 goto ret; 592 walkexpr(&n->left, init); 593 walkexprlist(n->list, init); 594 ll = ascompatte(n->op, n, 0, getthis(t), list1(n->left->left), 0, init); 595 lr = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init); 596 ll = concat(ll, lr); 597 n->left->left = N; 598 ullmancalc(n->left); 599 n->list = reorder1(ll); 600 goto ret; 601 602 case OAS: 603 *init = concat(*init, n->ninit); 604 n->ninit = nil; 605 606 walkexpr(&n->left, init); 607 n->left = safeexpr(n->left, init); 608 609 if(oaslit(n, init)) 610 goto ret; 611 612 if(n->right == N) 613 goto ret; 614 615 switch(n->right->op) { 616 default: 617 walkexpr(&n->right, init); 618 break; 619 620 case ORECV: 621 // x = <-c; n->left is x, n->right->left is c. 622 // orderstmt made sure x is addressable. 623 walkexpr(&n->right->left, init); 624 n1 = nod(OADDR, n->left, N); 625 r = n->right->left; // the channel 626 n = mkcall1(chanfn("chanrecv1", 2, r->type), T, init, typename(r->type), r, n1); 627 walkexpr(&n, init); 628 goto ret; 629 } 630 631 if(n->left != N && n->right != N) { 632 r = convas(nod(OAS, n->left, n->right), init); 633 r->dodata = n->dodata; 634 n = r; 635 } 636 637 goto ret; 638 639 case OAS2: 640 *init = concat(*init, n->ninit); 641 n->ninit = nil; 642 walkexprlistsafe(n->list, init); 643 walkexprlistsafe(n->rlist, init); 644 ll = ascompatee(OAS, n->list, n->rlist, init); 645 ll = reorder3(ll); 646 n = liststmt(ll); 647 goto ret; 648 649 case OAS2FUNC: 650 // a,b,... = fn() 651 *init = concat(*init, n->ninit); 652 n->ninit = nil; 653 r = n->rlist->n; 654 walkexprlistsafe(n->list, init); 655 walkexpr(&r, init); 656 657 ll = ascompatet(n->op, n->list, &r->type, 0, init); 658 n = liststmt(concat(list1(r), ll)); 659 goto ret; 660 661 case OAS2RECV: 662 // x, y = <-c 663 // orderstmt made sure x is addressable. 664 *init = concat(*init, n->ninit); 665 n->ninit = nil; 666 r = n->rlist->n; 667 walkexprlistsafe(n->list, init); 668 walkexpr(&r->left, init); 669 if(isblank(n->list->n)) 670 n1 = nodnil(); 671 else 672 n1 = nod(OADDR, n->list->n, N); 673 n1->etype = 1; // addr does not escape 674 fn = chanfn("chanrecv2", 2, r->left->type); 675 r = mkcall1(fn, types[TBOOL], init, typename(r->left->type), r->left, n1); 676 n = nod(OAS, n->list->next->n, r); 677 typecheck(&n, Etop); 678 goto ret; 679 680 case OAS2MAPR: 681 // a,b = m[i]; 682 *init = concat(*init, n->ninit); 683 n->ninit = nil; 684 r = n->rlist->n; 685 walkexprlistsafe(n->list, init); 686 walkexpr(&r->left, init); 687 walkexpr(&r->right, init); 688 t = r->left->type; 689 p = nil; 690 if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing. 691 switch(simsimtype(t->down)) { 692 case TINT32: 693 case TUINT32: 694 p = "mapaccess2_fast32"; 695 break; 696 case TINT64: 697 case TUINT64: 698 p = "mapaccess2_fast64"; 699 break; 700 case TSTRING: 701 p = "mapaccess2_faststr"; 702 break; 703 } 704 } 705 if(p != nil) { 706 // fast versions take key by value 707 key = r->right; 708 } else { 709 // standard version takes key by reference 710 // orderexpr made sure key is addressable. 711 key = nod(OADDR, r->right, N); 712 p = "mapaccess2"; 713 } 714 715 // from: 716 // a,b = m[i] 717 // to: 718 // var,b = mapaccess2*(t, m, i) 719 // a = *var 720 a = n->list->n; 721 var = temp(ptrto(t->type)); 722 var->typecheck = 1; 723 fn = mapfn(p, t); 724 r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, key); 725 n->rlist = list1(r); 726 n->op = OAS2FUNC; 727 n->list->n = var; 728 walkexpr(&n, init); 729 *init = list(*init, n); 730 n = nod(OAS, a, nod(OIND, var, N)); 731 typecheck(&n, Etop); 732 walkexpr(&n, init); 733 // mapaccess needs a zero value to be at least this big. 734 if(zerosize < t->type->width) 735 zerosize = t->type->width; 736 // TODO: ptr is always non-nil, so disable nil check for this OIND op. 737 goto ret; 738 739 case ODELETE: 740 *init = concat(*init, n->ninit); 741 n->ninit = nil; 742 map = n->list->n; 743 key = n->list->next->n; 744 walkexpr(&map, init); 745 walkexpr(&key, init); 746 // orderstmt made sure key is addressable. 747 key = nod(OADDR, key, N); 748 t = map->type; 749 n = mkcall1(mapfndel("mapdelete", t), T, init, typename(t), map, key); 750 goto ret; 751 752 case OAS2DOTTYPE: 753 // a,b = i.(T) 754 *init = concat(*init, n->ninit); 755 n->ninit = nil; 756 r = n->rlist->n; 757 walkexprlistsafe(n->list, init); 758 if(isblank(n->list->n) && !isinter(r->type)) { 759 strcpy(buf, "assert"); 760 p = buf+strlen(buf); 761 if(isnilinter(r->left->type)) 762 *p++ = 'E'; 763 else 764 *p++ = 'I'; 765 *p++ = '2'; 766 *p++ = 'T'; 767 *p++ = 'O'; 768 *p++ = 'K'; 769 *p = '\0'; 770 771 fn = syslook(buf, 1); 772 ll = list1(typename(r->type)); 773 ll = list(ll, r->left); 774 argtype(fn, r->left->type); 775 n1 = nod(OCALL, fn, N); 776 n1->list = ll; 777 n = nod(OAS, n->list->next->n, n1); 778 typecheck(&n, Etop); 779 walkexpr(&n, init); 780 goto ret; 781 } 782 783 r->op = ODOTTYPE2; 784 walkexpr(&r, init); 785 ll = ascompatet(n->op, n->list, &r->type, 0, init); 786 n = liststmt(concat(list1(r), ll)); 787 goto ret; 788 789 case ODOTTYPE: 790 case ODOTTYPE2: 791 // Build name of function: assertI2E2 etc. 792 strcpy(buf, "assert"); 793 p = buf+strlen(buf); 794 if(isnilinter(n->left->type)) 795 *p++ = 'E'; 796 else 797 *p++ = 'I'; 798 *p++ = '2'; 799 if(isnilinter(n->type)) 800 *p++ = 'E'; 801 else if(isinter(n->type)) 802 *p++ = 'I'; 803 else 804 *p++ = 'T'; 805 if(n->op == ODOTTYPE2) 806 *p++ = '2'; 807 *p = '\0'; 808 809 fn = syslook(buf, 1); 810 ll = list1(typename(n->type)); 811 ll = list(ll, n->left); 812 argtype(fn, n->left->type); 813 argtype(fn, n->type); 814 n = nod(OCALL, fn, N); 815 n->list = ll; 816 typecheck(&n, Erv | Efnstruct); 817 walkexpr(&n, init); 818 goto ret; 819 820 case OCONVIFACE: 821 walkexpr(&n->left, init); 822 823 // Optimize convT2E as a two-word copy when T is uintptr-shaped. 824 if(!isinter(n->left->type) && isnilinter(n->type) && 825 (n->left->type->width == widthptr) && 826 isint[simsimtype(n->left->type)]) { 827 l = nod(OEFACE, typename(n->left->type), n->left); 828 l->type = n->type; 829 l->typecheck = n->typecheck; 830 n = l; 831 goto ret; 832 } 833 834 // Build name of function: convI2E etc. 835 // Not all names are possible 836 // (e.g., we'll never generate convE2E or convE2I). 837 strcpy(buf, "conv"); 838 p = buf+strlen(buf); 839 if(isnilinter(n->left->type)) 840 *p++ = 'E'; 841 else if(isinter(n->left->type)) 842 *p++ = 'I'; 843 else 844 *p++ = 'T'; 845 *p++ = '2'; 846 if(isnilinter(n->type)) 847 *p++ = 'E'; 848 else 849 *p++ = 'I'; 850 *p = '\0'; 851 852 fn = syslook(buf, 1); 853 ll = nil; 854 if(!isinter(n->left->type)) 855 ll = list(ll, typename(n->left->type)); 856 if(!isnilinter(n->type)) 857 ll = list(ll, typename(n->type)); 858 if(!isinter(n->left->type) && !isnilinter(n->type)){ 859 sym = pkglookup(smprint("%-T.%-T", n->left->type, n->type), itabpkg); 860 if(sym->def == N) { 861 l = nod(ONAME, N, N); 862 l->sym = sym; 863 l->type = ptrto(types[TUINT8]); 864 l->addable = 1; 865 l->class = PEXTERN; 866 l->xoffset = 0; 867 sym->def = l; 868 ggloblsym(sym, widthptr, 1, 0); 869 } 870 l = nod(OADDR, sym->def, N); 871 l->addable = 1; 872 ll = list(ll, l); 873 874 if(n->left->type->width == widthptr && 875 isint[simsimtype(n->left->type)]) { 876 /* For pointer types, we can make a special form of optimization 877 * 878 * These statements are put onto the expression init list: 879 * Itab *tab = atomicloadtype(&cache); 880 * if(tab == nil) 881 * tab = typ2Itab(type, itype, &cache); 882 * 883 * The CONVIFACE expression is replaced with this: 884 * OEFACE{tab, ptr}; 885 */ 886 l = temp(ptrto(types[TUINT8])); 887 888 n1 = nod(OAS, l, sym->def); 889 typecheck(&n1, Etop); 890 *init = list(*init, n1); 891 892 fn = syslook("typ2Itab", 1); 893 n1 = nod(OCALL, fn, N); 894 n1->list = ll; 895 typecheck(&n1, Erv); 896 walkexpr(&n1, init); 897 898 n2 = nod(OIF, N, N); 899 n2->ntest = nod(OEQ, l, nodnil()); 900 n2->nbody = list1(nod(OAS, l, n1)); 901 n2->likely = -1; 902 typecheck(&n2, Etop); 903 *init = list(*init, n2); 904 905 l = nod(OEFACE, l, n->left); 906 l->typecheck = n->typecheck; 907 l->type = n->type; 908 n = l; 909 goto ret; 910 } 911 } 912 if(isinter(n->left->type)) { 913 ll = list(ll, n->left); 914 } else { 915 // regular types are passed by reference to avoid C vararg calls 916 // orderexpr arranged for n->left to be a temporary for all 917 // the conversions it could see. comparison of an interface 918 // with a non-interface, especially in a switch on interface value 919 // with non-interface cases, is not visible to orderstmt, so we 920 // have to fall back on allocating a temp here. 921 if(islvalue(n->left)) 922 ll = list(ll, nod(OADDR, n->left, N)); 923 else 924 ll = list(ll, nod(OADDR, copyexpr(n->left, n->left->type, init), N)); 925 } 926 argtype(fn, n->left->type); 927 argtype(fn, n->type); 928 dowidth(fn->type); 929 n = nod(OCALL, fn, N); 930 n->list = ll; 931 typecheck(&n, Erv); 932 walkexpr(&n, init); 933 goto ret; 934 935 case OCONV: 936 case OCONVNOP: 937 if(thechar == '5') { 938 if(isfloat[n->left->type->etype]) { 939 if(n->type->etype == TINT64) { 940 n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64])); 941 goto ret; 942 } 943 if(n->type->etype == TUINT64) { 944 n = mkcall("float64touint64", n->type, init, conv(n->left, types[TFLOAT64])); 945 goto ret; 946 } 947 } 948 if(isfloat[n->type->etype]) { 949 if(n->left->type->etype == TINT64) { 950 n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64])); 951 goto ret; 952 } 953 if(n->left->type->etype == TUINT64) { 954 n = mkcall("uint64tofloat64", n->type, init, conv(n->left, types[TUINT64])); 955 goto ret; 956 } 957 } 958 } 959 walkexpr(&n->left, init); 960 goto ret; 961 962 case OANDNOT: 963 walkexpr(&n->left, init); 964 n->op = OAND; 965 n->right = nod(OCOM, n->right, N); 966 typecheck(&n->right, Erv); 967 walkexpr(&n->right, init); 968 goto ret; 969 970 case OMUL: 971 walkexpr(&n->left, init); 972 walkexpr(&n->right, init); 973 walkmul(&n, init); 974 goto ret; 975 976 case ODIV: 977 case OMOD: 978 walkexpr(&n->left, init); 979 walkexpr(&n->right, init); 980 /* 981 * rewrite complex div into function call. 982 */ 983 et = n->left->type->etype; 984 if(iscomplex[et] && n->op == ODIV) { 985 t = n->type; 986 n = mkcall("complex128div", types[TCOMPLEX128], init, 987 conv(n->left, types[TCOMPLEX128]), 988 conv(n->right, types[TCOMPLEX128])); 989 n = conv(n, t); 990 goto ret; 991 } 992 // Nothing to do for float divisions. 993 if(isfloat[et]) 994 goto ret; 995 996 // Try rewriting as shifts or magic multiplies. 997 walkdiv(&n, init); 998 999 /* 1000 * rewrite 64-bit div and mod into function calls 1001 * on 32-bit architectures. 1002 */ 1003 switch(n->op) { 1004 case OMOD: 1005 case ODIV: 1006 if(widthreg >= 8 || (et != TUINT64 && et != TINT64)) 1007 goto ret; 1008 if(et == TINT64) 1009 strcpy(namebuf, "int64"); 1010 else 1011 strcpy(namebuf, "uint64"); 1012 if(n->op == ODIV) 1013 strcat(namebuf, "div"); 1014 else 1015 strcat(namebuf, "mod"); 1016 n = mkcall(namebuf, n->type, init, 1017 conv(n->left, types[et]), conv(n->right, types[et])); 1018 break; 1019 default: 1020 break; 1021 } 1022 goto ret; 1023 1024 case OINDEX: 1025 walkexpr(&n->left, init); 1026 // save the original node for bounds checking elision. 1027 // If it was a ODIV/OMOD walk might rewrite it. 1028 r = n->right; 1029 walkexpr(&n->right, init); 1030 1031 // if range of type cannot exceed static array bound, 1032 // disable bounds check. 1033 if(n->bounded) 1034 goto ret; 1035 t = n->left->type; 1036 if(t != T && isptr[t->etype]) 1037 t = t->type; 1038 if(isfixedarray(t)) { 1039 n->bounded = bounded(r, t->bound); 1040 if(debug['m'] && n->bounded && !isconst(n->right, CTINT)) 1041 warn("index bounds check elided"); 1042 if(smallintconst(n->right) && !n->bounded) 1043 yyerror("index out of bounds"); 1044 } else if(isconst(n->left, CTSTR)) { 1045 n->bounded = bounded(r, n->left->val.u.sval->len); 1046 if(debug['m'] && n->bounded && !isconst(n->right, CTINT)) 1047 warn("index bounds check elided"); 1048 if(smallintconst(n->right)) { 1049 if(!n->bounded) 1050 yyerror("index out of bounds"); 1051 else { 1052 // replace "abc"[1] with 'b'. 1053 // delayed until now because "abc"[1] is not 1054 // an ideal constant. 1055 v = mpgetfix(n->right->val.u.xval); 1056 nodconst(n, n->type, n->left->val.u.sval->s[v]); 1057 n->typecheck = 1; 1058 } 1059 } 1060 } 1061 1062 if(isconst(n->right, CTINT)) 1063 if(mpcmpfixfix(n->right->val.u.xval, &mpzero) < 0 || 1064 mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0) 1065 yyerror("index out of bounds"); 1066 goto ret; 1067 1068 case OINDEXMAP: 1069 if(n->etype == 1) 1070 goto ret; 1071 walkexpr(&n->left, init); 1072 walkexpr(&n->right, init); 1073 1074 t = n->left->type; 1075 p = nil; 1076 if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing. 1077 switch(simsimtype(t->down)) { 1078 case TINT32: 1079 case TUINT32: 1080 p = "mapaccess1_fast32"; 1081 break; 1082 case TINT64: 1083 case TUINT64: 1084 p = "mapaccess1_fast64"; 1085 break; 1086 case TSTRING: 1087 p = "mapaccess1_faststr"; 1088 break; 1089 } 1090 } 1091 if(p != nil) { 1092 // fast versions take key by value 1093 key = n->right; 1094 } else { 1095 // standard version takes key by reference. 1096 // orderexpr made sure key is addressable. 1097 key = nod(OADDR, n->right, N); 1098 p = "mapaccess1"; 1099 } 1100 n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, key); 1101 n = nod(OIND, n, N); 1102 n->type = t->type; 1103 n->typecheck = 1; 1104 // mapaccess needs a zero value to be at least this big. 1105 if(zerosize < t->type->width) 1106 zerosize = t->type->width; 1107 goto ret; 1108 1109 case ORECV: 1110 fatal("walkexpr ORECV"); // should see inside OAS only 1111 1112 case OSLICE: 1113 if(n->right != N && n->right->left == N && n->right->right == N) { // noop 1114 walkexpr(&n->left, init); 1115 n = n->left; 1116 goto ret; 1117 } 1118 // fallthrough 1119 case OSLICEARR: 1120 case OSLICESTR: 1121 if(n->right == N) // already processed 1122 goto ret; 1123 1124 walkexpr(&n->left, init); 1125 // cgen_slice can't handle string literals as source 1126 // TODO the OINDEX case is a bug elsewhere that needs to be traced. it causes a crash on ([2][]int{ ... })[1][lo:hi] 1127 if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left->op == OINDEX)) 1128 n->left = copyexpr(n->left, n->left->type, init); 1129 else 1130 n->left = safeexpr(n->left, init); 1131 walkexpr(&n->right->left, init); 1132 n->right->left = safeexpr(n->right->left, init); 1133 walkexpr(&n->right->right, init); 1134 n->right->right = safeexpr(n->right->right, init); 1135 n = sliceany(n, init); // chops n->right, sets n->list 1136 goto ret; 1137 1138 case OSLICE3: 1139 case OSLICE3ARR: 1140 if(n->right == N) // already processed 1141 goto ret; 1142 1143 walkexpr(&n->left, init); 1144 // TODO the OINDEX case is a bug elsewhere that needs to be traced. it causes a crash on ([2][]int{ ... })[1][lo:hi] 1145 // TODO the comment on the previous line was copied from case OSLICE. it might not even be true. 1146 if(n->left->op == OINDEX) 1147 n->left = copyexpr(n->left, n->left->type, init); 1148 else 1149 n->left = safeexpr(n->left, init); 1150 walkexpr(&n->right->left, init); 1151 n->right->left = safeexpr(n->right->left, init); 1152 walkexpr(&n->right->right->left, init); 1153 n->right->right->left = safeexpr(n->right->right->left, init); 1154 walkexpr(&n->right->right->right, init); 1155 n->right->right->right = safeexpr(n->right->right->right, init); 1156 n = sliceany(n, init); // chops n->right, sets n->list 1157 goto ret; 1158 1159 case OADDR: 1160 walkexpr(&n->left, init); 1161 goto ret; 1162 1163 case ONEW: 1164 if(n->esc == EscNone && n->type->type->width < (1<<16)) { 1165 r = temp(n->type->type); 1166 r = nod(OAS, r, N); // zero temp 1167 typecheck(&r, Etop); 1168 *init = list(*init, r); 1169 r = nod(OADDR, r->left, N); 1170 typecheck(&r, Erv); 1171 n = r; 1172 } else { 1173 n = callnew(n->type->type); 1174 } 1175 goto ret; 1176 1177 case OCMPSTR: 1178 // If one argument to the comparison is an empty string, 1179 // comparing the lengths instead will yield the same result 1180 // without the function call. 1181 if((isconst(n->left, CTSTR) && n->left->val.u.sval->len == 0) || 1182 (isconst(n->right, CTSTR) && n->right->val.u.sval->len == 0)) { 1183 r = nod(n->etype, nod(OLEN, n->left, N), nod(OLEN, n->right, N)); 1184 typecheck(&r, Erv); 1185 walkexpr(&r, init); 1186 r->type = n->type; 1187 n = r; 1188 goto ret; 1189 } 1190 1191 // s + "badgerbadgerbadger" == "badgerbadgerbadger" 1192 if((n->etype == OEQ || n->etype == ONE) && 1193 isconst(n->right, CTSTR) && 1194 n->left->op == OADDSTR && count(n->left->list) == 2 && 1195 isconst(n->left->list->next->n, CTSTR) && 1196 cmpslit(n->right, n->left->list->next->n) == 0) { 1197 r = nod(n->etype, nod(OLEN, n->left->list->n, N), nodintconst(0)); 1198 typecheck(&r, Erv); 1199 walkexpr(&r, init); 1200 r->type = n->type; 1201 n = r; 1202 goto ret; 1203 } 1204 1205 if(n->etype == OEQ || n->etype == ONE) { 1206 // prepare for rewrite below 1207 n->left = cheapexpr(n->left, init); 1208 n->right = cheapexpr(n->right, init); 1209 1210 r = mkcall("eqstring", types[TBOOL], init, 1211 conv(n->left, types[TSTRING]), 1212 conv(n->right, types[TSTRING])); 1213 1214 // quick check of len before full compare for == or != 1215 if(n->etype == OEQ) { 1216 // len(left) == len(right) && eqstring(left, right) 1217 r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r); 1218 } else { 1219 // len(left) != len(right) || !eqstring(left, right) 1220 r = nod(ONOT, r, N); 1221 r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r); 1222 } 1223 typecheck(&r, Erv); 1224 walkexpr(&r, nil); 1225 } else { 1226 // sys_cmpstring(s1, s2) :: 0 1227 r = mkcall("cmpstring", types[TINT], init, 1228 conv(n->left, types[TSTRING]), 1229 conv(n->right, types[TSTRING])); 1230 r = nod(n->etype, r, nodintconst(0)); 1231 } 1232 1233 typecheck(&r, Erv); 1234 if(n->type->etype != TBOOL) fatal("cmp %T", n->type); 1235 r->type = n->type; 1236 n = r; 1237 goto ret; 1238 1239 case OADDSTR: 1240 n = addstr(n, init); 1241 goto ret; 1242 1243 case OAPPEND: 1244 if(n->isddd) 1245 n = appendslice(n, init); // also works for append(slice, string). 1246 else 1247 n = append(n, init); 1248 goto ret; 1249 1250 case OCOPY: 1251 n = copyany(n, init, flag_race); 1252 goto ret; 1253 1254 case OCLOSE: 1255 // cannot use chanfn - closechan takes any, not chan any 1256 fn = syslook("closechan", 1); 1257 argtype(fn, n->left->type); 1258 n = mkcall1(fn, T, init, n->left); 1259 goto ret; 1260 1261 case OMAKECHAN: 1262 n = mkcall1(chanfn("makechan", 1, n->type), n->type, init, 1263 typename(n->type), 1264 conv(n->left, types[TINT64])); 1265 goto ret; 1266 1267 case OMAKEMAP: 1268 t = n->type; 1269 1270 fn = syslook("makemap", 1); 1271 argtype(fn, t->down); // any-1 1272 argtype(fn, t->type); // any-2 1273 1274 n = mkcall1(fn, n->type, init, 1275 typename(n->type), 1276 conv(n->left, types[TINT64])); 1277 goto ret; 1278 1279 case OMAKESLICE: 1280 l = n->left; 1281 r = n->right; 1282 if(r == nil) 1283 l = r = safeexpr(l, init); 1284 t = n->type; 1285 if(n->esc == EscNone 1286 && smallintconst(l) && smallintconst(r) 1287 && (t->type->width == 0 || mpgetfix(r->val.u.xval) < (1ULL<<16) / t->type->width)) { 1288 // var arr [r]T 1289 // n = arr[:l] 1290 t = aindex(r, t->type); // [r]T 1291 var = temp(t); 1292 a = nod(OAS, var, N); // zero temp 1293 typecheck(&a, Etop); 1294 *init = list(*init, a); 1295 r = nod(OSLICE, var, nod(OKEY, N, l)); // arr[:l] 1296 r = conv(r, n->type); // in case n->type is named. 1297 typecheck(&r, Erv); 1298 walkexpr(&r, init); 1299 n = r; 1300 } else { 1301 // makeslice(t *Type, nel int64, max int64) (ary []any) 1302 fn = syslook("makeslice", 1); 1303 argtype(fn, t->type); // any-1 1304 n = mkcall1(fn, n->type, init, 1305 typename(n->type), 1306 conv(l, types[TINT64]), 1307 conv(r, types[TINT64])); 1308 } 1309 goto ret; 1310 1311 case ORUNESTR: 1312 // sys_intstring(v) 1313 n = mkcall("intstring", n->type, init, 1314 conv(n->left, types[TINT64])); 1315 goto ret; 1316 1317 case OARRAYBYTESTR: 1318 // slicebytetostring([]byte) string; 1319 n = mkcall("slicebytetostring", n->type, init, n->left); 1320 goto ret; 1321 1322 case OARRAYBYTESTRTMP: 1323 // slicebytetostringtmp([]byte) string; 1324 n = mkcall("slicebytetostringtmp", n->type, init, n->left); 1325 goto ret; 1326 1327 case OARRAYRUNESTR: 1328 // slicerunetostring([]rune) string; 1329 n = mkcall("slicerunetostring", n->type, init, n->left); 1330 goto ret; 1331 1332 case OSTRARRAYBYTE: 1333 // stringtoslicebyte(string) []byte; 1334 n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING])); 1335 goto ret; 1336 1337 case OSTRARRAYRUNE: 1338 // stringtoslicerune(string) []rune 1339 n = mkcall("stringtoslicerune", n->type, init, n->left); 1340 goto ret; 1341 1342 case OCMPIFACE: 1343 // ifaceeq(i1 any-1, i2 any-2) (ret bool); 1344 if(!eqtype(n->left->type, n->right->type)) 1345 fatal("ifaceeq %O %T %T", n->op, n->left->type, n->right->type); 1346 if(isnilinter(n->left->type)) 1347 fn = syslook("efaceeq", 1); 1348 else 1349 fn = syslook("ifaceeq", 1); 1350 1351 n->right = cheapexpr(n->right, init); 1352 n->left = cheapexpr(n->left, init); 1353 argtype(fn, n->right->type); 1354 argtype(fn, n->left->type); 1355 r = mkcall1(fn, n->type, init, n->left, n->right); 1356 if(n->etype == ONE) 1357 r = nod(ONOT, r, N); 1358 1359 // check itable/type before full compare. 1360 if(n->etype == OEQ) 1361 r = nod(OANDAND, nod(OEQ, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r); 1362 else 1363 r = nod(OOROR, nod(ONE, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r); 1364 typecheck(&r, Erv); 1365 walkexpr(&r, init); 1366 r->type = n->type; 1367 n = r; 1368 goto ret; 1369 1370 case OARRAYLIT: 1371 case OMAPLIT: 1372 case OSTRUCTLIT: 1373 case OPTRLIT: 1374 // XXX TODO do we need to clear var? 1375 var = temp(n->type); 1376 anylit(0, n, var, init); 1377 n = var; 1378 goto ret; 1379 1380 case OSEND: 1381 n1 = n->right; 1382 n1 = assignconv(n1, n->left->type->type, "chan send"); 1383 walkexpr(&n1, init); 1384 n1 = nod(OADDR, n1, N); 1385 n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1); 1386 goto ret; 1387 1388 case OCLOSURE: 1389 n = walkclosure(n, init); 1390 goto ret; 1391 1392 case OCALLPART: 1393 n = walkpartialcall(n, init); 1394 goto ret; 1395 } 1396 fatal("missing switch %O", n->op); 1397 1398 ret: 1399 // Expressions that are constant at run time but not 1400 // considered const by the language spec are not turned into 1401 // constants until walk. For example, if n is y%1 == 0, the 1402 // walk of y%1 may have replaced it by 0. 1403 // Check whether n with its updated args is itself now a constant. 1404 t = n->type; 1405 evconst(n); 1406 n->type = t; 1407 if(n->op == OLITERAL) 1408 typecheck(&n, Erv); 1409 1410 ullmancalc(n); 1411 1412 if(debug['w'] && n != N) 1413 dump("walk", n); 1414 1415 lineno = lno; 1416 *np = n; 1417 } 1418 1419 static Node* 1420 ascompatee1(int op, Node *l, Node *r, NodeList **init) 1421 { 1422 Node *n; 1423 USED(op); 1424 1425 // convas will turn map assigns into function calls, 1426 // making it impossible for reorder3 to work. 1427 n = nod(OAS, l, r); 1428 if(l->op == OINDEXMAP) 1429 return n; 1430 1431 return convas(n, init); 1432 } 1433 1434 static NodeList* 1435 ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init) 1436 { 1437 NodeList *ll, *lr, *nn; 1438 1439 /* 1440 * check assign expression list to 1441 * a expression list. called in 1442 * expr-list = expr-list 1443 */ 1444 1445 // ensure order of evaluation for function calls 1446 for(ll=nl; ll; ll=ll->next) 1447 ll->n = safeexpr(ll->n, init); 1448 for(lr=nr; lr; lr=lr->next) 1449 lr->n = safeexpr(lr->n, init); 1450 1451 nn = nil; 1452 for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next) { 1453 // Do not generate 'x = x' during return. See issue 4014. 1454 if(op == ORETURN && ll->n == lr->n) 1455 continue; 1456 nn = list(nn, ascompatee1(op, ll->n, lr->n, init)); 1457 } 1458 1459 // cannot happen: caller checked that lists had same length 1460 if(ll || lr) 1461 yyerror("error in shape across %+H %O %+H / %d %d [%s]", nl, op, nr, count(nl), count(nr), curfn->nname->sym->name); 1462 return nn; 1463 } 1464 1465 /* 1466 * l is an lv and rt is the type of an rv 1467 * return 1 if this implies a function call 1468 * evaluating the lv or a function call 1469 * in the conversion of the types 1470 */ 1471 static int 1472 fncall(Node *l, Type *rt) 1473 { 1474 if(l->ullman >= UINF || l->op == OINDEXMAP) 1475 return 1; 1476 if(eqtype(l->type, rt)) 1477 return 0; 1478 return 1; 1479 } 1480 1481 static NodeList* 1482 ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init) 1483 { 1484 Node *l, *tmp, *a; 1485 NodeList *ll; 1486 Type *r; 1487 Iter saver; 1488 int ucount; 1489 NodeList *nn, *mm; 1490 1491 USED(op); 1492 1493 /* 1494 * check assign type list to 1495 * a expression list. called in 1496 * expr-list = func() 1497 */ 1498 r = structfirst(&saver, nr); 1499 nn = nil; 1500 mm = nil; 1501 ucount = 0; 1502 for(ll=nl; ll; ll=ll->next) { 1503 if(r == T) 1504 break; 1505 l = ll->n; 1506 if(isblank(l)) { 1507 r = structnext(&saver); 1508 continue; 1509 } 1510 1511 // any lv that causes a fn call must be 1512 // deferred until all the return arguments 1513 // have been pulled from the output arguments 1514 if(fncall(l, r->type)) { 1515 tmp = temp(r->type); 1516 typecheck(&tmp, Erv); 1517 a = nod(OAS, l, tmp); 1518 a = convas(a, init); 1519 mm = list(mm, a); 1520 l = tmp; 1521 } 1522 1523 a = nod(OAS, l, nodarg(r, fp)); 1524 a = convas(a, init); 1525 ullmancalc(a); 1526 if(a->ullman >= UINF) 1527 ucount++; 1528 nn = list(nn, a); 1529 r = structnext(&saver); 1530 } 1531 1532 if(ll != nil || r != T) 1533 yyerror("ascompatet: assignment count mismatch: %d = %d", 1534 count(nl), structcount(*nr)); 1535 1536 if(ucount) 1537 fatal("ascompatet: too many function calls evaluating parameters"); 1538 return concat(nn, mm); 1539 } 1540 1541 /* 1542 * package all the arguments that match a ... T parameter into a []T. 1543 */ 1544 static NodeList* 1545 mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, Node *ddd) 1546 { 1547 Node *a, *n; 1548 Type *tslice; 1549 int esc; 1550 1551 esc = EscUnknown; 1552 if(ddd != nil) 1553 esc = ddd->esc; 1554 1555 tslice = typ(TARRAY); 1556 tslice->type = l->type->type; 1557 tslice->bound = -1; 1558 1559 if(count(lr0) == 0) { 1560 n = nodnil(); 1561 n->type = tslice; 1562 } else { 1563 n = nod(OCOMPLIT, N, typenod(tslice)); 1564 if(ddd != nil) 1565 n->alloc = ddd->alloc; // temporary to use 1566 n->list = lr0; 1567 n->esc = esc; 1568 typecheck(&n, Erv); 1569 if(n->type == T) 1570 fatal("mkdotargslice: typecheck failed"); 1571 walkexpr(&n, init); 1572 } 1573 1574 a = nod(OAS, nodarg(l, fp), n); 1575 nn = list(nn, convas(a, init)); 1576 return nn; 1577 } 1578 1579 /* 1580 * helpers for shape errors 1581 */ 1582 static char* 1583 dumptypes(Type **nl, char *what) 1584 { 1585 int first; 1586 Type *l; 1587 Iter savel; 1588 Fmt fmt; 1589 1590 fmtstrinit(&fmt); 1591 fmtprint(&fmt, "\t"); 1592 first = 1; 1593 for(l = structfirst(&savel, nl); l != T; l = structnext(&savel)) { 1594 if(first) 1595 first = 0; 1596 else 1597 fmtprint(&fmt, ", "); 1598 fmtprint(&fmt, "%T", l); 1599 } 1600 if(first) 1601 fmtprint(&fmt, "[no arguments %s]", what); 1602 return fmtstrflush(&fmt); 1603 } 1604 1605 static char* 1606 dumpnodetypes(NodeList *l, char *what) 1607 { 1608 int first; 1609 Node *r; 1610 Fmt fmt; 1611 1612 fmtstrinit(&fmt); 1613 fmtprint(&fmt, "\t"); 1614 first = 1; 1615 for(; l; l=l->next) { 1616 r = l->n; 1617 if(first) 1618 first = 0; 1619 else 1620 fmtprint(&fmt, ", "); 1621 fmtprint(&fmt, "%T", r->type); 1622 } 1623 if(first) 1624 fmtprint(&fmt, "[no arguments %s]", what); 1625 return fmtstrflush(&fmt); 1626 } 1627 1628 /* 1629 * check assign expression list to 1630 * a type list. called in 1631 * return expr-list 1632 * func(expr-list) 1633 */ 1634 static NodeList* 1635 ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeList **init) 1636 { 1637 Type *l, *ll; 1638 Node *r, *a; 1639 NodeList *nn, *lr0, *alist; 1640 Iter savel; 1641 char *l1, *l2; 1642 1643 lr0 = lr; 1644 l = structfirst(&savel, nl); 1645 r = N; 1646 if(lr) 1647 r = lr->n; 1648 nn = nil; 1649 1650 // f(g()) where g has multiple return values 1651 if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) { 1652 // optimization - can do block copy 1653 if(eqtypenoname(r->type, *nl)) { 1654 a = nodarg(*nl, fp); 1655 r = nod(OCONVNOP, r, N); 1656 r->type = a->type; 1657 nn = list1(convas(nod(OAS, a, r), init)); 1658 goto ret; 1659 } 1660 1661 // conversions involved. 1662 // copy into temporaries. 1663 alist = nil; 1664 for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) { 1665 a = temp(l->type); 1666 alist = list(alist, a); 1667 } 1668 a = nod(OAS2, N, N); 1669 a->list = alist; 1670 a->rlist = lr; 1671 typecheck(&a, Etop); 1672 walkstmt(&a); 1673 *init = list(*init, a); 1674 lr = alist; 1675 r = lr->n; 1676 l = structfirst(&savel, nl); 1677 } 1678 1679 loop: 1680 if(l != T && l->isddd) { 1681 // the ddd parameter must be last 1682 ll = structnext(&savel); 1683 if(ll != T) 1684 yyerror("... must be last argument"); 1685 1686 // special case -- 1687 // only if we are assigning a single ddd 1688 // argument to a ddd parameter then it is 1689 // passed thru unencapsulated 1690 if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) { 1691 a = nod(OAS, nodarg(l, fp), r); 1692 a = convas(a, init); 1693 nn = list(nn, a); 1694 goto ret; 1695 } 1696 1697 // normal case -- make a slice of all 1698 // remaining arguments and pass it to 1699 // the ddd parameter. 1700 nn = mkdotargslice(lr, nn, l, fp, init, call->right); 1701 goto ret; 1702 } 1703 1704 if(l == T || r == N) { 1705 if(l != T || r != N) { 1706 l1 = dumptypes(nl, "expected"); 1707 l2 = dumpnodetypes(lr0, "given"); 1708 if(l != T) 1709 yyerror("not enough arguments to %O\n%s\n%s", op, l1, l2); 1710 else 1711 yyerror("too many arguments to %O\n%s\n%s", op, l1, l2); 1712 } 1713 goto ret; 1714 } 1715 1716 a = nod(OAS, nodarg(l, fp), r); 1717 a = convas(a, init); 1718 nn = list(nn, a); 1719 1720 l = structnext(&savel); 1721 r = N; 1722 lr = lr->next; 1723 if(lr != nil) 1724 r = lr->n; 1725 goto loop; 1726 1727 ret: 1728 for(lr=nn; lr; lr=lr->next) 1729 lr->n->typecheck = 1; 1730 return nn; 1731 } 1732 1733 // generate code for print 1734 static Node* 1735 walkprint(Node *nn, NodeList **init, int defer) 1736 { 1737 Node *r; 1738 Node *n; 1739 NodeList *l, *all; 1740 Node *on; 1741 Type *t; 1742 int notfirst, et, op; 1743 NodeList *calls, *intypes, *args; 1744 Fmt fmt; 1745 1746 on = nil; 1747 op = nn->op; 1748 all = nn->list; 1749 calls = nil; 1750 notfirst = 0; 1751 intypes = nil; 1752 args = nil; 1753 1754 memset(&fmt, 0, sizeof fmt); 1755 if(defer) { 1756 // defer print turns into defer printf with format string 1757 fmtstrinit(&fmt); 1758 intypes = list(intypes, nod(ODCLFIELD, N, typenod(types[TSTRING]))); 1759 args = list1(nod(OXXX, N, N)); 1760 } 1761 1762 for(l=all; l; l=l->next) { 1763 if(notfirst) { 1764 if(defer) 1765 fmtprint(&fmt, " "); 1766 else 1767 calls = list(calls, mkcall("printsp", T, init)); 1768 } 1769 notfirst = op == OPRINTN; 1770 1771 n = l->n; 1772 if(n->op == OLITERAL) { 1773 switch(n->val.ctype) { 1774 case CTRUNE: 1775 defaultlit(&n, runetype); 1776 break; 1777 case CTINT: 1778 defaultlit(&n, types[TINT64]); 1779 break; 1780 case CTFLT: 1781 defaultlit(&n, types[TFLOAT64]); 1782 break; 1783 } 1784 } 1785 if(n->op != OLITERAL && n->type && n->type->etype == TIDEAL) 1786 defaultlit(&n, types[TINT64]); 1787 defaultlit(&n, nil); 1788 l->n = n; 1789 if(n->type == T || n->type->etype == TFORW) 1790 continue; 1791 1792 t = n->type; 1793 et = n->type->etype; 1794 if(isinter(n->type)) { 1795 if(defer) { 1796 if(isnilinter(n->type)) 1797 fmtprint(&fmt, "%%e"); 1798 else 1799 fmtprint(&fmt, "%%i"); 1800 } else { 1801 if(isnilinter(n->type)) 1802 on = syslook("printeface", 1); 1803 else 1804 on = syslook("printiface", 1); 1805 argtype(on, n->type); // any-1 1806 } 1807 } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) { 1808 if(defer) { 1809 fmtprint(&fmt, "%%p"); 1810 } else { 1811 on = syslook("printpointer", 1); 1812 argtype(on, n->type); // any-1 1813 } 1814 } else if(isslice(n->type)) { 1815 if(defer) { 1816 fmtprint(&fmt, "%%a"); 1817 } else { 1818 on = syslook("printslice", 1); 1819 argtype(on, n->type); // any-1 1820 } 1821 } else if(isint[et]) { 1822 if(defer) { 1823 if(et == TUINT64) 1824 fmtprint(&fmt, "%%U"); 1825 else { 1826 fmtprint(&fmt, "%%D"); 1827 t = types[TINT64]; 1828 } 1829 } else { 1830 if(et == TUINT64) 1831 on = syslook("printuint", 0); 1832 else 1833 on = syslook("printint", 0); 1834 } 1835 } else if(isfloat[et]) { 1836 if(defer) { 1837 fmtprint(&fmt, "%%f"); 1838 t = types[TFLOAT64]; 1839 } else 1840 on = syslook("printfloat", 0); 1841 } else if(iscomplex[et]) { 1842 if(defer) { 1843 fmtprint(&fmt, "%%C"); 1844 t = types[TCOMPLEX128]; 1845 } else 1846 on = syslook("printcomplex", 0); 1847 } else if(et == TBOOL) { 1848 if(defer) 1849 fmtprint(&fmt, "%%t"); 1850 else 1851 on = syslook("printbool", 0); 1852 } else if(et == TSTRING) { 1853 if(defer) 1854 fmtprint(&fmt, "%%S"); 1855 else 1856 on = syslook("printstring", 0); 1857 } else { 1858 badtype(OPRINT, n->type, T); 1859 continue; 1860 } 1861 1862 if(!defer) { 1863 t = *getinarg(on->type); 1864 if(t != nil) 1865 t = t->type; 1866 if(t != nil) 1867 t = t->type; 1868 } 1869 1870 if(!eqtype(t, n->type)) { 1871 n = nod(OCONV, n, N); 1872 n->type = t; 1873 } 1874 1875 if(defer) { 1876 intypes = list(intypes, nod(ODCLFIELD, N, typenod(t))); 1877 args = list(args, n); 1878 } else { 1879 r = nod(OCALL, on, N); 1880 r->list = list1(n); 1881 calls = list(calls, r); 1882 } 1883 } 1884 1885 if(defer) { 1886 if(op == OPRINTN) 1887 fmtprint(&fmt, "\n"); 1888 on = syslook("goprintf", 1); 1889 on->type = functype(nil, intypes, nil); 1890 args->n = nod(OLITERAL, N, N); 1891 args->n->val.ctype = CTSTR; 1892 args->n->val.u.sval = strlit(fmtstrflush(&fmt)); 1893 r = nod(OCALL, on, N); 1894 r->list = args; 1895 typecheck(&r, Etop); 1896 walkexpr(&r, init); 1897 } else { 1898 if(op == OPRINTN) 1899 calls = list(calls, mkcall("printnl", T, nil)); 1900 typechecklist(calls, Etop); 1901 walkexprlist(calls, init); 1902 1903 r = nod(OEMPTY, N, N); 1904 typecheck(&r, Etop); 1905 walkexpr(&r, init); 1906 r->ninit = calls; 1907 } 1908 return r; 1909 } 1910 1911 Node* 1912 callnew(Type *t) 1913 { 1914 Node *fn; 1915 1916 dowidth(t); 1917 fn = syslook("new", 1); 1918 argtype(fn, t); 1919 return mkcall1(fn, ptrto(t), nil, typename(t)); 1920 } 1921 1922 static Node* 1923 convas(Node *n, NodeList **init) 1924 { 1925 Type *lt, *rt; 1926 Node *map, *key, *val; 1927 1928 if(n->op != OAS) 1929 fatal("convas: not OAS %O", n->op); 1930 1931 n->typecheck = 1; 1932 1933 if(n->left == N || n->right == N) 1934 goto out; 1935 1936 lt = n->left->type; 1937 rt = n->right->type; 1938 if(lt == T || rt == T) 1939 goto out; 1940 1941 if(isblank(n->left)) { 1942 defaultlit(&n->right, T); 1943 goto out; 1944 } 1945 1946 if(n->left->op == OINDEXMAP) { 1947 map = n->left->left; 1948 key = n->left->right; 1949 val = n->right; 1950 walkexpr(&map, init); 1951 walkexpr(&key, init); 1952 walkexpr(&val, init); 1953 // orderexpr made sure key and val are addressable. 1954 key = nod(OADDR, key, N); 1955 val = nod(OADDR, val, N); 1956 n = mkcall1(mapfn("mapassign1", map->type), T, init, 1957 typename(map->type), map, key, val); 1958 goto out; 1959 } 1960 1961 if(eqtype(lt, rt)) 1962 goto out; 1963 1964 n->right = assignconv(n->right, lt, "assignment"); 1965 walkexpr(&n->right, init); 1966 1967 out: 1968 ullmancalc(n); 1969 return n; 1970 } 1971 1972 /* 1973 * from ascompat[te] 1974 * evaluating actual function arguments. 1975 * f(a,b) 1976 * if there is exactly one function expr, 1977 * then it is done first. otherwise must 1978 * make temp variables 1979 */ 1980 static NodeList* 1981 reorder1(NodeList *all) 1982 { 1983 Node *f, *a, *n; 1984 NodeList *l, *r, *g; 1985 int c, d, t; 1986 1987 c = 0; // function calls 1988 t = 0; // total parameters 1989 1990 for(l=all; l; l=l->next) { 1991 n = l->n; 1992 t++; 1993 ullmancalc(n); 1994 if(n->ullman >= UINF) 1995 c++; 1996 } 1997 if(c == 0 || t == 1) 1998 return all; 1999 2000 g = nil; // fncalls assigned to tempnames 2001 f = N; // last fncall assigned to stack 2002 r = nil; // non fncalls and tempnames assigned to stack 2003 d = 0; 2004 for(l=all; l; l=l->next) { 2005 n = l->n; 2006 if(n->ullman < UINF) { 2007 r = list(r, n); 2008 continue; 2009 } 2010 d++; 2011 if(d == c) { 2012 f = n; 2013 continue; 2014 } 2015 2016 // make assignment of fncall to tempname 2017 a = temp(n->right->type); 2018 a = nod(OAS, a, n->right); 2019 g = list(g, a); 2020 2021 // put normal arg assignment on list 2022 // with fncall replaced by tempname 2023 n->right = a->left; 2024 r = list(r, n); 2025 } 2026 2027 if(f != N) 2028 g = list(g, f); 2029 return concat(g, r); 2030 } 2031 2032 static void reorder3save(Node**, NodeList*, NodeList*, NodeList**); 2033 static int aliased(Node*, NodeList*, NodeList*); 2034 2035 /* 2036 * from ascompat[ee] 2037 * a,b = c,d 2038 * simultaneous assignment. there cannot 2039 * be later use of an earlier lvalue. 2040 * 2041 * function calls have been removed. 2042 */ 2043 static NodeList* 2044 reorder3(NodeList *all) 2045 { 2046 NodeList *list, *early, *mapinit; 2047 Node *l; 2048 2049 // If a needed expression may be affected by an 2050 // earlier assignment, make an early copy of that 2051 // expression and use the copy instead. 2052 early = nil; 2053 mapinit = nil; 2054 for(list=all; list; list=list->next) { 2055 l = list->n->left; 2056 2057 // Save subexpressions needed on left side. 2058 // Drill through non-dereferences. 2059 for(;;) { 2060 if(l->op == ODOT || l->op == OPAREN) { 2061 l = l->left; 2062 continue; 2063 } 2064 if(l->op == OINDEX && isfixedarray(l->left->type)) { 2065 reorder3save(&l->right, all, list, &early); 2066 l = l->left; 2067 continue; 2068 } 2069 break; 2070 } 2071 switch(l->op) { 2072 default: 2073 fatal("reorder3 unexpected lvalue %#O", l->op); 2074 case ONAME: 2075 break; 2076 case OINDEX: 2077 case OINDEXMAP: 2078 reorder3save(&l->left, all, list, &early); 2079 reorder3save(&l->right, all, list, &early); 2080 if(l->op == OINDEXMAP) 2081 list->n = convas(list->n, &mapinit); 2082 break; 2083 case OIND: 2084 case ODOTPTR: 2085 reorder3save(&l->left, all, list, &early); 2086 } 2087 2088 // Save expression on right side. 2089 reorder3save(&list->n->right, all, list, &early); 2090 } 2091 2092 early = concat(mapinit, early); 2093 return concat(early, all); 2094 } 2095 2096 static int vmatch2(Node*, Node*); 2097 static int varexpr(Node*); 2098 2099 /* 2100 * if the evaluation of *np would be affected by the 2101 * assignments in all up to but not including stop, 2102 * copy into a temporary during *early and 2103 * replace *np with that temp. 2104 */ 2105 static void 2106 reorder3save(Node **np, NodeList *all, NodeList *stop, NodeList **early) 2107 { 2108 Node *n, *q; 2109 2110 n = *np; 2111 if(!aliased(n, all, stop)) 2112 return; 2113 2114 q = temp(n->type); 2115 q = nod(OAS, q, n); 2116 typecheck(&q, Etop); 2117 *early = list(*early, q); 2118 *np = q->left; 2119 } 2120 2121 /* 2122 * what's the outer value that a write to n affects? 2123 * outer value means containing struct or array. 2124 */ 2125 Node* 2126 outervalue(Node *n) 2127 { 2128 for(;;) { 2129 if(n->op == ODOT || n->op == OPAREN) { 2130 n = n->left; 2131 continue; 2132 } 2133 if(n->op == OINDEX && isfixedarray(n->left->type)) { 2134 n = n->left; 2135 continue; 2136 } 2137 break; 2138 } 2139 return n; 2140 } 2141 2142 /* 2143 * Is it possible that the computation of n might be 2144 * affected by writes in as up to but not including stop? 2145 */ 2146 static int 2147 aliased(Node *n, NodeList *all, NodeList *stop) 2148 { 2149 int memwrite, varwrite; 2150 Node *a; 2151 NodeList *l; 2152 2153 if(n == N) 2154 return 0; 2155 2156 // Look for obvious aliasing: a variable being assigned 2157 // during the all list and appearing in n. 2158 // Also record whether there are any writes to main memory. 2159 // Also record whether there are any writes to variables 2160 // whose addresses have been taken. 2161 memwrite = 0; 2162 varwrite = 0; 2163 for(l=all; l!=stop; l=l->next) { 2164 a = outervalue(l->n->left); 2165 if(a->op != ONAME) { 2166 memwrite = 1; 2167 continue; 2168 } 2169 switch(n->class) { 2170 default: 2171 varwrite = 1; 2172 continue; 2173 case PAUTO: 2174 case PPARAM: 2175 case PPARAMOUT: 2176 if(n->addrtaken) { 2177 varwrite = 1; 2178 continue; 2179 } 2180 if(vmatch2(a, n)) { 2181 // Direct hit. 2182 return 1; 2183 } 2184 } 2185 } 2186 2187 // The variables being written do not appear in n. 2188 // However, n might refer to computed addresses 2189 // that are being written. 2190 2191 // If no computed addresses are affected by the writes, no aliasing. 2192 if(!memwrite && !varwrite) 2193 return 0; 2194 2195 // If n does not refer to computed addresses 2196 // (that is, if n only refers to variables whose addresses 2197 // have not been taken), no aliasing. 2198 if(varexpr(n)) 2199 return 0; 2200 2201 // Otherwise, both the writes and n refer to computed memory addresses. 2202 // Assume that they might conflict. 2203 return 1; 2204 } 2205 2206 /* 2207 * does the evaluation of n only refer to variables 2208 * whose addresses have not been taken? 2209 * (and no other memory) 2210 */ 2211 static int 2212 varexpr(Node *n) 2213 { 2214 if(n == N) 2215 return 1; 2216 2217 switch(n->op) { 2218 case OLITERAL: 2219 return 1; 2220 case ONAME: 2221 switch(n->class) { 2222 case PAUTO: 2223 case PPARAM: 2224 case PPARAMOUT: 2225 if(!n->addrtaken) 2226 return 1; 2227 } 2228 return 0; 2229 2230 case OADD: 2231 case OSUB: 2232 case OOR: 2233 case OXOR: 2234 case OMUL: 2235 case ODIV: 2236 case OMOD: 2237 case OLSH: 2238 case ORSH: 2239 case OAND: 2240 case OANDNOT: 2241 case OPLUS: 2242 case OMINUS: 2243 case OCOM: 2244 case OPAREN: 2245 case OANDAND: 2246 case OOROR: 2247 case ODOT: // but not ODOTPTR 2248 case OCONV: 2249 case OCONVNOP: 2250 case OCONVIFACE: 2251 case ODOTTYPE: 2252 return varexpr(n->left) && varexpr(n->right); 2253 } 2254 2255 // Be conservative. 2256 return 0; 2257 } 2258 2259 /* 2260 * is the name l mentioned in r? 2261 */ 2262 static int 2263 vmatch2(Node *l, Node *r) 2264 { 2265 NodeList *ll; 2266 2267 if(r == N) 2268 return 0; 2269 switch(r->op) { 2270 case ONAME: 2271 // match each right given left 2272 return l == r; 2273 case OLITERAL: 2274 return 0; 2275 } 2276 if(vmatch2(l, r->left)) 2277 return 1; 2278 if(vmatch2(l, r->right)) 2279 return 1; 2280 for(ll=r->list; ll; ll=ll->next) 2281 if(vmatch2(l, ll->n)) 2282 return 1; 2283 return 0; 2284 } 2285 2286 /* 2287 * is any name mentioned in l also mentioned in r? 2288 * called by sinit.c 2289 */ 2290 int 2291 vmatch1(Node *l, Node *r) 2292 { 2293 NodeList *ll; 2294 2295 /* 2296 * isolate all left sides 2297 */ 2298 if(l == N || r == N) 2299 return 0; 2300 switch(l->op) { 2301 case ONAME: 2302 switch(l->class) { 2303 case PPARAM: 2304 case PPARAMREF: 2305 case PAUTO: 2306 break; 2307 default: 2308 // assignment to non-stack variable 2309 // must be delayed if right has function calls. 2310 if(r->ullman >= UINF) 2311 return 1; 2312 break; 2313 } 2314 return vmatch2(l, r); 2315 case OLITERAL: 2316 return 0; 2317 } 2318 if(vmatch1(l->left, r)) 2319 return 1; 2320 if(vmatch1(l->right, r)) 2321 return 1; 2322 for(ll=l->list; ll; ll=ll->next) 2323 if(vmatch1(ll->n, r)) 2324 return 1; 2325 return 0; 2326 } 2327 2328 /* 2329 * walk through argin parameters. 2330 * generate and return code to allocate 2331 * copies of escaped parameters to the heap. 2332 */ 2333 static NodeList* 2334 paramstoheap(Type **argin, int out) 2335 { 2336 Type *t; 2337 Iter savet; 2338 Node *v; 2339 NodeList *nn; 2340 2341 nn = nil; 2342 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) { 2343 v = t->nname; 2344 if(v && v->sym && v->sym->name[0] == '~' && v->sym->name[1] == 'r') // unnamed result 2345 v = N; 2346 // In precisestack mode, the garbage collector assumes results 2347 // are always live, so zero them always. 2348 if(out && (precisestack_enabled || (v == N && hasdefer))) { 2349 // Defer might stop a panic and show the 2350 // return values as they exist at the time of panic. 2351 // Make sure to zero them on entry to the function. 2352 nn = list(nn, nod(OAS, nodarg(t, 1), N)); 2353 } 2354 if(v == N || !(v->class & PHEAP)) 2355 continue; 2356 2357 // generate allocation & copying code 2358 if(v->alloc == nil) 2359 v->alloc = callnew(v->type); 2360 nn = list(nn, nod(OAS, v->heapaddr, v->alloc)); 2361 if((v->class & ~PHEAP) != PPARAMOUT) 2362 nn = list(nn, nod(OAS, v, v->stackparam)); 2363 } 2364 return nn; 2365 } 2366 2367 /* 2368 * walk through argout parameters copying back to stack 2369 */ 2370 static NodeList* 2371 returnsfromheap(Type **argin) 2372 { 2373 Type *t; 2374 Iter savet; 2375 Node *v; 2376 NodeList *nn; 2377 2378 nn = nil; 2379 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) { 2380 v = t->nname; 2381 if(v == N || v->class != (PHEAP|PPARAMOUT)) 2382 continue; 2383 nn = list(nn, nod(OAS, v->stackparam, v)); 2384 } 2385 return nn; 2386 } 2387 2388 /* 2389 * take care of migrating any function in/out args 2390 * between the stack and the heap. adds code to 2391 * curfn's before and after lists. 2392 */ 2393 static void 2394 heapmoves(void) 2395 { 2396 NodeList *nn; 2397 int32 lno; 2398 2399 lno = lineno; 2400 lineno = curfn->lineno; 2401 nn = paramstoheap(getthis(curfn->type), 0); 2402 nn = concat(nn, paramstoheap(getinarg(curfn->type), 0)); 2403 nn = concat(nn, paramstoheap(getoutarg(curfn->type), 1)); 2404 curfn->enter = concat(curfn->enter, nn); 2405 lineno = curfn->endlineno; 2406 curfn->exit = returnsfromheap(getoutarg(curfn->type)); 2407 lineno = lno; 2408 } 2409 2410 static Node* 2411 vmkcall(Node *fn, Type *t, NodeList **init, va_list va) 2412 { 2413 int i, n; 2414 Node *r; 2415 NodeList *args; 2416 2417 if(fn->type == T || fn->type->etype != TFUNC) 2418 fatal("mkcall %N %T", fn, fn->type); 2419 2420 args = nil; 2421 n = fn->type->intuple; 2422 for(i=0; i<n; i++) 2423 args = list(args, va_arg(va, Node*)); 2424 2425 r = nod(OCALL, fn, N); 2426 r->list = args; 2427 if(fn->type->outtuple > 0) 2428 typecheck(&r, Erv | Efnstruct); 2429 else 2430 typecheck(&r, Etop); 2431 walkexpr(&r, init); 2432 r->type = t; 2433 return r; 2434 } 2435 2436 Node* 2437 mkcall(char *name, Type *t, NodeList **init, ...) 2438 { 2439 Node *r; 2440 va_list va; 2441 2442 va_start(va, init); 2443 r = vmkcall(syslook(name, 0), t, init, va); 2444 va_end(va); 2445 return r; 2446 } 2447 2448 Node* 2449 mkcall1(Node *fn, Type *t, NodeList **init, ...) 2450 { 2451 Node *r; 2452 va_list va; 2453 2454 va_start(va, init); 2455 r = vmkcall(fn, t, init, va); 2456 va_end(va); 2457 return r; 2458 } 2459 2460 Node* 2461 conv(Node *n, Type *t) 2462 { 2463 if(eqtype(n->type, t)) 2464 return n; 2465 n = nod(OCONV, n, N); 2466 n->type = t; 2467 typecheck(&n, Erv); 2468 return n; 2469 } 2470 2471 Node* 2472 chanfn(char *name, int n, Type *t) 2473 { 2474 Node *fn; 2475 int i; 2476 2477 if(t->etype != TCHAN) 2478 fatal("chanfn %T", t); 2479 fn = syslook(name, 1); 2480 for(i=0; i<n; i++) 2481 argtype(fn, t->type); 2482 return fn; 2483 } 2484 2485 static Node* 2486 mapfn(char *name, Type *t) 2487 { 2488 Node *fn; 2489 2490 if(t->etype != TMAP) 2491 fatal("mapfn %T", t); 2492 fn = syslook(name, 1); 2493 argtype(fn, t->down); 2494 argtype(fn, t->type); 2495 argtype(fn, t->down); 2496 argtype(fn, t->type); 2497 return fn; 2498 } 2499 2500 static Node* 2501 mapfndel(char *name, Type *t) 2502 { 2503 Node *fn; 2504 2505 if(t->etype != TMAP) 2506 fatal("mapfn %T", t); 2507 fn = syslook(name, 1); 2508 argtype(fn, t->down); 2509 argtype(fn, t->type); 2510 argtype(fn, t->down); 2511 return fn; 2512 } 2513 2514 static Node* 2515 addstr(Node *n, NodeList **init) 2516 { 2517 Node *r, *cat, *slice; 2518 NodeList *args, *l; 2519 int c; 2520 Type *t; 2521 2522 // orderexpr rewrote OADDSTR to have a list of strings. 2523 c = count(n->list); 2524 if(c < 2) 2525 yyerror("addstr count %d too small", c); 2526 2527 // build list of string arguments 2528 args = nil; 2529 for(l=n->list; l != nil; l=l->next) 2530 args = list(args, conv(l->n, types[TSTRING])); 2531 2532 if(c <= 5) { 2533 // small numbers of strings use direct runtime helpers. 2534 // note: orderexpr knows this cutoff too. 2535 snprint(namebuf, sizeof(namebuf), "concatstring%d", c); 2536 } else { 2537 // large numbers of strings are passed to the runtime as a slice. 2538 strcpy(namebuf, "concatstrings"); 2539 t = typ(TARRAY); 2540 t->type = types[TSTRING]; 2541 t->bound = -1; 2542 slice = nod(OCOMPLIT, N, typenod(t)); 2543 slice->alloc = n->alloc; 2544 slice->list = args; 2545 slice->esc = EscNone; 2546 args = list1(slice); 2547 } 2548 cat = syslook(namebuf, 1); 2549 r = nod(OCALL, cat, N); 2550 r->list = args; 2551 typecheck(&r, Erv); 2552 walkexpr(&r, init); 2553 r->type = n->type; 2554 2555 return r; 2556 } 2557 2558 // expand append(l1, l2...) to 2559 // init { 2560 // s := l1 2561 // if n := len(l1) + len(l2) - cap(s); n > 0 { 2562 // s = growslice(s, n) 2563 // } 2564 // s = s[:len(l1)+len(l2)] 2565 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) 2566 // } 2567 // s 2568 // 2569 // l2 is allowed to be a string. 2570 static Node* 2571 appendslice(Node *n, NodeList **init) 2572 { 2573 NodeList *l; 2574 Node *l1, *l2, *nt, *nif, *fn; 2575 Node *nptr1, *nptr2, *nwid; 2576 Node *s; 2577 2578 walkexprlistsafe(n->list, init); 2579 2580 // walkexprlistsafe will leave OINDEX (s[n]) alone if both s 2581 // and n are name or literal, but those may index the slice we're 2582 // modifying here. Fix explicitly. 2583 for(l=n->list; l; l=l->next) 2584 l->n = cheapexpr(l->n, init); 2585 2586 l1 = n->list->n; 2587 l2 = n->list->next->n; 2588 2589 s = temp(l1->type); // var s []T 2590 l = nil; 2591 l = list(l, nod(OAS, s, l1)); // s = l1 2592 2593 nt = temp(types[TINT]); 2594 nif = nod(OIF, N, N); 2595 // n := len(s) + len(l2) - cap(s) 2596 nif->ninit = list1(nod(OAS, nt, 2597 nod(OSUB, nod(OADD, nod(OLEN, s, N), nod(OLEN, l2, N)), nod(OCAP, s, N)))); 2598 nif->ntest = nod(OGT, nt, nodintconst(0)); 2599 // instantiate growslice(Type*, []any, int64) []any 2600 fn = syslook("growslice", 1); 2601 argtype(fn, s->type->type); 2602 argtype(fn, s->type->type); 2603 2604 // s = growslice(T, s, n) 2605 nif->nbody = list1(nod(OAS, s, mkcall1(fn, s->type, &nif->ninit, 2606 typename(s->type), 2607 s, 2608 conv(nt, types[TINT64])))); 2609 2610 l = list(l, nif); 2611 2612 if(flag_race) { 2613 // rely on runtime to instrument copy. 2614 // copy(s[len(l1):len(l1)+len(l2)], l2) 2615 nptr1 = nod(OSLICE, s, nod(OKEY, 2616 nod(OLEN, l1, N), 2617 nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N)))); 2618 nptr1->etype = 1; 2619 nptr2 = l2; 2620 if(l2->type->etype == TSTRING) 2621 fn = syslook("slicestringcopy", 1); 2622 else 2623 fn = syslook("copy", 1); 2624 argtype(fn, l1->type); 2625 argtype(fn, l2->type); 2626 nt = mkcall1(fn, types[TINT], &l, 2627 nptr1, nptr2, 2628 nodintconst(s->type->type->width)); 2629 l = list(l, nt); 2630 } else { 2631 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) 2632 nptr1 = nod(OINDEX, s, nod(OLEN, l1, N)); 2633 nptr1->bounded = 1; 2634 nptr1 = nod(OADDR, nptr1, N); 2635 2636 nptr2 = nod(OSPTR, l2, N); 2637 2638 fn = syslook("memmove", 1); 2639 argtype(fn, s->type->type); // 1 old []any 2640 argtype(fn, s->type->type); // 2 ret []any 2641 2642 nwid = cheapexpr(conv(nod(OLEN, l2, N), types[TUINTPTR]), &l); 2643 nwid = nod(OMUL, nwid, nodintconst(s->type->type->width)); 2644 nt = mkcall1(fn, T, &l, nptr1, nptr2, nwid); 2645 l = list(l, nt); 2646 } 2647 2648 // s = s[:len(l1)+len(l2)] 2649 nt = nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N)); 2650 nt = nod(OSLICE, s, nod(OKEY, N, nt)); 2651 nt->etype = 1; 2652 l = list(l, nod(OAS, s, nt)); 2653 2654 typechecklist(l, Etop); 2655 walkstmtlist(l); 2656 *init = concat(*init, l); 2657 return s; 2658 } 2659 2660 // expand append(src, a [, b]* ) to 2661 // 2662 // init { 2663 // s := src 2664 // const argc = len(args) - 1 2665 // if cap(s) - len(s) < argc { 2666 // s = growslice(s, argc) 2667 // } 2668 // n := len(s) 2669 // s = s[:n+argc] 2670 // s[n] = a 2671 // s[n+1] = b 2672 // ... 2673 // } 2674 // s 2675 static Node* 2676 append(Node *n, NodeList **init) 2677 { 2678 NodeList *l, *a; 2679 Node *nsrc, *ns, *nn, *na, *nx, *fn; 2680 int argc; 2681 2682 walkexprlistsafe(n->list, init); 2683 2684 // walkexprlistsafe will leave OINDEX (s[n]) alone if both s 2685 // and n are name or literal, but those may index the slice we're 2686 // modifying here. Fix explicitly. 2687 for(l=n->list; l; l=l->next) 2688 l->n = cheapexpr(l->n, init); 2689 2690 nsrc = n->list->n; 2691 2692 // Resolve slice type of multi-valued return. 2693 if(istype(nsrc->type, TSTRUCT)) 2694 nsrc->type = nsrc->type->type->type; 2695 argc = count(n->list) - 1; 2696 if (argc < 1) { 2697 return nsrc; 2698 } 2699 2700 l = nil; 2701 2702 ns = temp(nsrc->type); 2703 l = list(l, nod(OAS, ns, nsrc)); // s = src 2704 2705 na = nodintconst(argc); // const argc 2706 nx = nod(OIF, N, N); // if cap(s) - len(s) < argc 2707 nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na); 2708 2709 fn = syslook("growslice", 1); // growslice(<type>, old []T, n int64) (ret []T) 2710 argtype(fn, ns->type->type); // 1 old []any 2711 argtype(fn, ns->type->type); // 2 ret []any 2712 2713 nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit, 2714 typename(ns->type), 2715 ns, 2716 conv(na, types[TINT64])))); 2717 l = list(l, nx); 2718 2719 nn = temp(types[TINT]); 2720 l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s) 2721 2722 nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc] 2723 nx->etype = 1; 2724 l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc] 2725 2726 for (a = n->list->next; a != nil; a = a->next) { 2727 nx = nod(OINDEX, ns, nn); // s[n] ... 2728 nx->bounded = 1; 2729 l = list(l, nod(OAS, nx, a->n)); // s[n] = arg 2730 if (a->next != nil) 2731 l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))); // n = n + 1 2732 } 2733 2734 typechecklist(l, Etop); 2735 walkstmtlist(l); 2736 *init = concat(*init, l); 2737 return ns; 2738 } 2739 2740 // Lower copy(a, b) to a memmove call or a runtime call. 2741 // 2742 // init { 2743 // n := len(a) 2744 // if n > len(b) { n = len(b) } 2745 // memmove(a.ptr, b.ptr, n*sizeof(elem(a))) 2746 // } 2747 // n; 2748 // 2749 // Also works if b is a string. 2750 // 2751 static Node* 2752 copyany(Node *n, NodeList **init, int runtimecall) 2753 { 2754 Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn; 2755 NodeList *l; 2756 2757 if(runtimecall) { 2758 if(n->right->type->etype == TSTRING) 2759 fn = syslook("slicestringcopy", 1); 2760 else 2761 fn = syslook("copy", 1); 2762 argtype(fn, n->left->type); 2763 argtype(fn, n->right->type); 2764 return mkcall1(fn, n->type, init, 2765 n->left, n->right, 2766 nodintconst(n->left->type->type->width)); 2767 } 2768 walkexpr(&n->left, init); 2769 walkexpr(&n->right, init); 2770 nl = temp(n->left->type); 2771 nr = temp(n->right->type); 2772 l = nil; 2773 l = list(l, nod(OAS, nl, n->left)); 2774 l = list(l, nod(OAS, nr, n->right)); 2775 2776 nfrm = nod(OSPTR, nr, N); 2777 nto = nod(OSPTR, nl, N); 2778 2779 nlen = temp(types[TINT]); 2780 // n = len(to) 2781 l = list(l, nod(OAS, nlen, nod(OLEN, nl, N))); 2782 // if n > len(frm) { n = len(frm) } 2783 nif = nod(OIF, N, N); 2784 nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N)); 2785 nif->nbody = list(nif->nbody, 2786 nod(OAS, nlen, nod(OLEN, nr, N))); 2787 l = list(l, nif); 2788 2789 // Call memmove. 2790 fn = syslook("memmove", 1); 2791 argtype(fn, nl->type->type); 2792 argtype(fn, nl->type->type); 2793 nwid = temp(types[TUINTPTR]); 2794 l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR]))); 2795 nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width)); 2796 l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid)); 2797 2798 typechecklist(l, Etop); 2799 walkstmtlist(l); 2800 *init = concat(*init, l); 2801 return nlen; 2802 } 2803 2804 // Generate frontend part for OSLICE[3][ARR|STR] 2805 // 2806 static Node* 2807 sliceany(Node* n, NodeList **init) 2808 { 2809 int bounded, slice3; 2810 Node *src, *lb, *hb, *cb, *bound, *chk, *chk0, *chk1, *chk2; 2811 int64 lbv, hbv, cbv, bv, w; 2812 Type *bt; 2813 2814 // print("before sliceany: %+N\n", n); 2815 2816 src = n->left; 2817 lb = n->right->left; 2818 slice3 = n->op == OSLICE3 || n->op == OSLICE3ARR; 2819 if(slice3) { 2820 hb = n->right->right->left; 2821 cb = n->right->right->right; 2822 } else { 2823 hb = n->right->right; 2824 cb = N; 2825 } 2826 2827 bounded = n->etype; 2828 2829 if(n->op == OSLICESTR) 2830 bound = nod(OLEN, src, N); 2831 else 2832 bound = nod(OCAP, src, N); 2833 2834 typecheck(&bound, Erv); 2835 walkexpr(&bound, init); // if src is an array, bound will be a const now. 2836 2837 // static checks if possible 2838 bv = 1LL<<50; 2839 if(isconst(bound, CTINT)) { 2840 if(!smallintconst(bound)) 2841 yyerror("array len too large"); 2842 else 2843 bv = mpgetfix(bound->val.u.xval); 2844 } 2845 2846 if(isconst(cb, CTINT)) { 2847 cbv = mpgetfix(cb->val.u.xval); 2848 if(cbv < 0 || cbv > bv) 2849 yyerror("slice index out of bounds"); 2850 } 2851 if(isconst(hb, CTINT)) { 2852 hbv = mpgetfix(hb->val.u.xval); 2853 if(hbv < 0 || hbv > bv) 2854 yyerror("slice index out of bounds"); 2855 } 2856 if(isconst(lb, CTINT)) { 2857 lbv = mpgetfix(lb->val.u.xval); 2858 if(lbv < 0 || lbv > bv) { 2859 yyerror("slice index out of bounds"); 2860 lbv = -1; 2861 } 2862 if(lbv == 0) 2863 lb = N; 2864 } 2865 2866 // dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison 2867 // generate 2868 // if hb > bound || lb > hb { panicslice() } 2869 chk = N; 2870 chk0 = N; 2871 chk1 = N; 2872 chk2 = N; 2873 2874 bt = types[simtype[TUINT]]; 2875 if(cb != N && cb->type->width > 4) 2876 bt = types[TUINT64]; 2877 if(hb != N && hb->type->width > 4) 2878 bt = types[TUINT64]; 2879 if(lb != N && lb->type->width > 4) 2880 bt = types[TUINT64]; 2881 2882 bound = cheapexpr(conv(bound, bt), init); 2883 2884 if(cb != N) { 2885 cb = cheapexpr(conv(cb, bt), init); 2886 if(!bounded) 2887 chk0 = nod(OLT, bound, cb); 2888 } else if(slice3) { 2889 // When we figure out what this means, implement it. 2890 fatal("slice3 with cb == N"); // rejected by parser 2891 } 2892 2893 if(hb != N) { 2894 hb = cheapexpr(conv(hb, bt), init); 2895 if(!bounded) { 2896 if(cb != N) 2897 chk1 = nod(OLT, cb, hb); 2898 else 2899 chk1 = nod(OLT, bound, hb); 2900 } 2901 } else if(slice3) { 2902 // When we figure out what this means, implement it. 2903 fatal("slice3 with hb == N"); // rejected by parser 2904 } else if(n->op == OSLICEARR) { 2905 hb = bound; 2906 } else { 2907 hb = nod(OLEN, src, N); 2908 typecheck(&hb, Erv); 2909 walkexpr(&hb, init); 2910 hb = cheapexpr(conv(hb, bt), init); 2911 } 2912 2913 if(lb != N) { 2914 lb = cheapexpr(conv(lb, bt), init); 2915 if(!bounded) 2916 chk2 = nod(OLT, hb, lb); 2917 } 2918 2919 if(chk0 != N || chk1 != N || chk2 != N) { 2920 chk = nod(OIF, N, N); 2921 chk->nbody = list1(mkcall("panicslice", T, init)); 2922 chk->likely = -1; 2923 if(chk0 != N) 2924 chk->ntest = chk0; 2925 if(chk1 != N) { 2926 if(chk->ntest == N) 2927 chk->ntest = chk1; 2928 else 2929 chk->ntest = nod(OOROR, chk->ntest, chk1); 2930 } 2931 if(chk2 != N) { 2932 if(chk->ntest == N) 2933 chk->ntest = chk2; 2934 else 2935 chk->ntest = nod(OOROR, chk->ntest, chk2); 2936 } 2937 typecheck(&chk, Etop); 2938 walkstmt(&chk); 2939 *init = concat(*init, chk->ninit); 2940 chk->ninit = nil; 2941 *init = list(*init, chk); 2942 } 2943 2944 // prepare new cap, len and offs for backend cgen_slice 2945 // cap = bound [ - lo ] 2946 n->right = N; 2947 n->list = nil; 2948 if(!slice3) 2949 cb = bound; 2950 if(lb == N) 2951 bound = conv(cb, types[simtype[TUINT]]); 2952 else 2953 bound = nod(OSUB, conv(cb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]])); 2954 typecheck(&bound, Erv); 2955 walkexpr(&bound, init); 2956 n->list = list(n->list, bound); 2957 2958 // len = hi [ - lo] 2959 if(lb == N) 2960 hb = conv(hb, types[simtype[TUINT]]); 2961 else 2962 hb = nod(OSUB, conv(hb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]])); 2963 typecheck(&hb, Erv); 2964 walkexpr(&hb, init); 2965 n->list = list(n->list, hb); 2966 2967 // offs = [width *] lo, but omit if zero 2968 if(lb != N) { 2969 if(n->op == OSLICESTR) 2970 w = 1; 2971 else 2972 w = n->type->type->width; 2973 lb = conv(lb, types[TUINTPTR]); 2974 if(w > 1) 2975 lb = nod(OMUL, nodintconst(w), lb); 2976 typecheck(&lb, Erv); 2977 walkexpr(&lb, init); 2978 n->list = list(n->list, lb); 2979 } 2980 2981 // print("after sliceany: %+N\n", n); 2982 2983 return n; 2984 } 2985 2986 static Node* 2987 eqfor(Type *t) 2988 { 2989 int a; 2990 Node *n; 2991 Node *ntype; 2992 Sym *sym; 2993 2994 // Should only arrive here with large memory or 2995 // a struct/array containing a non-memory field/element. 2996 // Small memory is handled inline, and single non-memory 2997 // is handled during type check (OCMPSTR etc). 2998 a = algtype1(t, nil); 2999 if(a != AMEM && a != -1) 3000 fatal("eqfor %T", t); 3001 3002 if(a == AMEM) { 3003 n = syslook("memequal", 1); 3004 argtype(n, t); 3005 argtype(n, t); 3006 return n; 3007 } 3008 3009 sym = typesymprefix(".eq", t); 3010 n = newname(sym); 3011 n->class = PFUNC; 3012 ntype = nod(OTFUNC, N, N); 3013 ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(types[TBOOL])))); 3014 ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); 3015 ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); 3016 ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); 3017 typecheck(&ntype, Etype); 3018 n->type = ntype->type; 3019 return n; 3020 } 3021 3022 static int 3023 countfield(Type *t) 3024 { 3025 Type *t1; 3026 int n; 3027 3028 n = 0; 3029 for(t1=t->type; t1!=T; t1=t1->down) 3030 n++; 3031 return n; 3032 } 3033 3034 static void 3035 walkcompare(Node **np, NodeList **init) 3036 { 3037 Node *n, *l, *r, *fn, *call, *a, *li, *ri, *expr; 3038 int andor, i; 3039 Type *t, *t1; 3040 static Node *tempbool; 3041 3042 n = *np; 3043 3044 // Must be comparison of array or struct. 3045 // Otherwise back end handles it. 3046 t = n->left->type; 3047 switch(t->etype) { 3048 default: 3049 return; 3050 case TARRAY: 3051 if(isslice(t)) 3052 return; 3053 break; 3054 case TSTRUCT: 3055 break; 3056 } 3057 3058 if(!islvalue(n->left) || !islvalue(n->right)) 3059 goto hard; 3060 3061 l = temp(ptrto(t)); 3062 a = nod(OAS, l, nod(OADDR, n->left, N)); 3063 a->right->etype = 1; // addr does not escape 3064 typecheck(&a, Etop); 3065 *init = list(*init, a); 3066 3067 r = temp(ptrto(t)); 3068 a = nod(OAS, r, nod(OADDR, n->right, N)); 3069 a->right->etype = 1; // addr does not escape 3070 typecheck(&a, Etop); 3071 *init = list(*init, a); 3072 3073 expr = N; 3074 andor = OANDAND; 3075 if(n->op == ONE) 3076 andor = OOROR; 3077 3078 if(t->etype == TARRAY && 3079 t->bound <= 4 && 3080 issimple[t->type->etype]) { 3081 // Four or fewer elements of a basic type. 3082 // Unroll comparisons. 3083 for(i=0; i<t->bound; i++) { 3084 li = nod(OINDEX, l, nodintconst(i)); 3085 ri = nod(OINDEX, r, nodintconst(i)); 3086 a = nod(n->op, li, ri); 3087 if(expr == N) 3088 expr = a; 3089 else 3090 expr = nod(andor, expr, a); 3091 } 3092 if(expr == N) 3093 expr = nodbool(n->op == OEQ); 3094 r = expr; 3095 goto ret; 3096 } 3097 3098 if(t->etype == TSTRUCT && countfield(t) <= 4) { 3099 // Struct of four or fewer fields. 3100 // Inline comparisons. 3101 for(t1=t->type; t1; t1=t1->down) { 3102 if(isblanksym(t1->sym)) 3103 continue; 3104 li = nod(OXDOT, l, newname(t1->sym)); 3105 ri = nod(OXDOT, r, newname(t1->sym)); 3106 a = nod(n->op, li, ri); 3107 if(expr == N) 3108 expr = a; 3109 else 3110 expr = nod(andor, expr, a); 3111 } 3112 if(expr == N) 3113 expr = nodbool(n->op == OEQ); 3114 r = expr; 3115 goto ret; 3116 } 3117 3118 // Chose not to inline, but still have addresses. 3119 // Call equality function directly. 3120 // The equality function requires a bool pointer for 3121 // storing its address, because it has to be callable 3122 // from C, and C can't access an ordinary Go return value. 3123 // To avoid creating many temporaries, cache one per function. 3124 if(tempbool == N || tempbool->curfn != curfn) 3125 tempbool = temp(types[TBOOL]); 3126 3127 call = nod(OCALL, eqfor(t), N); 3128 a = nod(OADDR, tempbool, N); 3129 a->etype = 1; // does not escape 3130 call->list = list(call->list, a); 3131 call->list = list(call->list, nodintconst(t->width)); 3132 call->list = list(call->list, l); 3133 call->list = list(call->list, r); 3134 typecheck(&call, Etop); 3135 walkstmt(&call); 3136 *init = list(*init, call); 3137 3138 // tempbool cannot be used directly as multiple comparison 3139 // expressions may exist in the same statement. Create another 3140 // temporary to hold the value (its address is not taken so it can 3141 // be optimized away). 3142 r = temp(types[TBOOL]); 3143 a = nod(OAS, r, tempbool); 3144 typecheck(&a, Etop); 3145 walkstmt(&a); 3146 *init = list(*init, a); 3147 3148 if(n->op != OEQ) 3149 r = nod(ONOT, r, N); 3150 goto ret; 3151 3152 hard: 3153 // Cannot take address of one or both of the operands. 3154 // Instead, pass directly to runtime helper function. 3155 // Easier on the stack than passing the address 3156 // of temporary variables, because we are better at reusing 3157 // the argument space than temporary variable space. 3158 fn = syslook("equal", 1); 3159 l = n->left; 3160 r = n->right; 3161 argtype(fn, n->left->type); 3162 argtype(fn, n->left->type); 3163 r = mkcall1(fn, n->type, init, typename(n->left->type), l, r); 3164 if(n->op == ONE) { 3165 r = nod(ONOT, r, N); 3166 } 3167 goto ret; 3168 3169 ret: 3170 typecheck(&r, Erv); 3171 walkexpr(&r, init); 3172 if(r->type != n->type) { 3173 r = nod(OCONVNOP, r, N); 3174 r->type = n->type; 3175 r->typecheck = 1; 3176 } 3177 *np = r; 3178 return; 3179 } 3180 3181 static int 3182 samecheap(Node *a, Node *b) 3183 { 3184 Node *ar, *br; 3185 while(a != N && b != N && a->op == b->op) { 3186 switch(a->op) { 3187 default: 3188 return 0; 3189 case ONAME: 3190 return a == b; 3191 case ODOT: 3192 case ODOTPTR: 3193 ar = a->right; 3194 br = b->right; 3195 if(ar->op != ONAME || br->op != ONAME || ar->sym != br->sym) 3196 return 0; 3197 break; 3198 case OINDEX: 3199 ar = a->right; 3200 br = b->right; 3201 if(!isconst(ar, CTINT) || !isconst(br, CTINT) || mpcmpfixfix(ar->val.u.xval, br->val.u.xval) != 0) 3202 return 0; 3203 break; 3204 } 3205 a = a->left; 3206 b = b->left; 3207 } 3208 return 0; 3209 } 3210 3211 static void 3212 walkrotate(Node **np) 3213 { 3214 int w, sl, sr, s; 3215 Node *l, *r; 3216 Node *n; 3217 3218 n = *np; 3219 3220 // Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value. 3221 l = n->left; 3222 r = n->right; 3223 if((n->op != OOR && n->op != OXOR) || 3224 (l->op != OLSH && l->op != ORSH) || 3225 (r->op != OLSH && r->op != ORSH) || 3226 n->type == T || issigned[n->type->etype] || 3227 l->op == r->op) { 3228 return; 3229 } 3230 3231 // Want same, side effect-free expression on lhs of both shifts. 3232 if(!samecheap(l->left, r->left)) 3233 return; 3234 3235 // Constants adding to width? 3236 w = l->type->width * 8; 3237 if(smallintconst(l->right) && smallintconst(r->right)) { 3238 if((sl=mpgetfix(l->right->val.u.xval)) >= 0 && (sr=mpgetfix(r->right->val.u.xval)) >= 0 && sl+sr == w) 3239 goto yes; 3240 return; 3241 } 3242 3243 // TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31). 3244 return; 3245 3246 yes: 3247 // Rewrite left shift half to left rotate. 3248 if(l->op == OLSH) 3249 n = l; 3250 else 3251 n = r; 3252 n->op = OLROT; 3253 3254 // Remove rotate 0 and rotate w. 3255 s = mpgetfix(n->right->val.u.xval); 3256 if(s == 0 || s == w) 3257 n = n->left; 3258 3259 *np = n; 3260 return; 3261 } 3262 3263 /* 3264 * walkmul rewrites integer multiplication by powers of two as shifts. 3265 */ 3266 static void 3267 walkmul(Node **np, NodeList **init) 3268 { 3269 Node *n, *nl, *nr; 3270 int pow, neg, w; 3271 3272 n = *np; 3273 if(!isint[n->type->etype]) 3274 return; 3275 3276 if(n->right->op == OLITERAL) { 3277 nl = n->left; 3278 nr = n->right; 3279 } else if(n->left->op == OLITERAL) { 3280 nl = n->right; 3281 nr = n->left; 3282 } else 3283 return; 3284 3285 neg = 0; 3286 3287 // x*0 is 0 (and side effects of x). 3288 if(mpgetfix(nr->val.u.xval) == 0) { 3289 cheapexpr(nl, init); 3290 nodconst(n, n->type, 0); 3291 goto ret; 3292 } 3293 3294 // nr is a constant. 3295 pow = powtwo(nr); 3296 if(pow < 0) 3297 return; 3298 if(pow >= 1000) { 3299 // negative power of 2, like -16 3300 neg = 1; 3301 pow -= 1000; 3302 } 3303 3304 w = nl->type->width*8; 3305 if(pow+1 >= w)// too big, shouldn't happen 3306 return; 3307 3308 nl = cheapexpr(nl, init); 3309 3310 if(pow == 0) { 3311 // x*1 is x 3312 n = nl; 3313 goto ret; 3314 } 3315 3316 n = nod(OLSH, nl, nodintconst(pow)); 3317 3318 ret: 3319 if(neg) 3320 n = nod(OMINUS, n, N); 3321 3322 typecheck(&n, Erv); 3323 walkexpr(&n, init); 3324 *np = n; 3325 } 3326 3327 /* 3328 * walkdiv rewrites division by a constant as less expensive 3329 * operations. 3330 */ 3331 static void 3332 walkdiv(Node **np, NodeList **init) 3333 { 3334 Node *n, *nl, *nr, *nc; 3335 Node *n1, *n2, *n3, *n4; 3336 int pow; // if >= 0, nr is 1<<pow 3337 int s; // 1 if nr is negative. 3338 int w; 3339 Type *twide; 3340 Magic m; 3341 3342 n = *np; 3343 if(n->right->op != OLITERAL) 3344 return; 3345 // nr is a constant. 3346 nl = cheapexpr(n->left, init); 3347 nr = n->right; 3348 3349 // special cases of mod/div 3350 // by a constant 3351 w = nl->type->width*8; 3352 s = 0; 3353 pow = powtwo(nr); 3354 if(pow >= 1000) { 3355 // negative power of 2 3356 s = 1; 3357 pow -= 1000; 3358 } 3359 3360 if(pow+1 >= w) { 3361 // divisor too large. 3362 return; 3363 } 3364 if(pow < 0) { 3365 goto divbymul; 3366 } 3367 3368 switch(pow) { 3369 case 0: 3370 if(n->op == OMOD) { 3371 // nl % 1 is zero. 3372 nodconst(n, n->type, 0); 3373 } else if(s) { 3374 // divide by -1 3375 n->op = OMINUS; 3376 n->right = N; 3377 } else { 3378 // divide by 1 3379 n = nl; 3380 } 3381 break; 3382 default: 3383 if(issigned[n->type->etype]) { 3384 if(n->op == OMOD) { 3385 // signed modulo 2^pow is like ANDing 3386 // with the last pow bits, but if nl < 0, 3387 // nl & (2^pow-1) is (nl+1)%2^pow - 1. 3388 nc = nod(OXXX, N, N); 3389 nodconst(nc, types[simtype[TUINT]], w-1); 3390 n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0. 3391 if(pow == 1) { 3392 typecheck(&n1, Erv); 3393 n1 = cheapexpr(n1, init); 3394 // n = (nl+ε)&1 -ε where ε=1 iff nl<0. 3395 n2 = nod(OSUB, nl, n1); 3396 nc = nod(OXXX, N, N); 3397 nodconst(nc, nl->type, 1); 3398 n3 = nod(OAND, n2, nc); 3399 n = nod(OADD, n3, n1); 3400 } else { 3401 // n = (nl+ε)&(nr-1) - ε where ε=2^pow-1 iff nl<0. 3402 nc = nod(OXXX, N, N); 3403 nodconst(nc, nl->type, (1LL<<pow)-1); 3404 n2 = nod(OAND, n1, nc); // n2 = 2^pow-1 iff nl<0. 3405 typecheck(&n2, Erv); 3406 n2 = cheapexpr(n2, init); 3407 3408 n3 = nod(OADD, nl, n2); 3409 n4 = nod(OAND, n3, nc); 3410 n = nod(OSUB, n4, n2); 3411 } 3412 break; 3413 } else { 3414 // arithmetic right shift does not give the correct rounding. 3415 // if nl >= 0, nl >> n == nl / nr 3416 // if nl < 0, we want to add 2^n-1 first. 3417 nc = nod(OXXX, N, N); 3418 nodconst(nc, types[simtype[TUINT]], w-1); 3419 n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0. 3420 if(pow == 1) { 3421 // nl+1 is nl-(-1) 3422 n->left = nod(OSUB, nl, n1); 3423 } else { 3424 // Do a logical right right on -1 to keep pow bits. 3425 nc = nod(OXXX, N, N); 3426 nodconst(nc, types[simtype[TUINT]], w-pow); 3427 n2 = nod(ORSH, conv(n1, tounsigned(nl->type)), nc); 3428 n->left = nod(OADD, nl, conv(n2, nl->type)); 3429 } 3430 // n = (nl + 2^pow-1) >> pow 3431 n->op = ORSH; 3432 nc = nod(OXXX, N, N); 3433 nodconst(nc, types[simtype[TUINT]], pow); 3434 n->right = nc; 3435 n->typecheck = 0; 3436 } 3437 if(s) 3438 n = nod(OMINUS, n, N); 3439 break; 3440 } 3441 nc = nod(OXXX, N, N); 3442 if(n->op == OMOD) { 3443 // n = nl & (nr-1) 3444 n->op = OAND; 3445 nodconst(nc, nl->type, mpgetfix(nr->val.u.xval)-1); 3446 } else { 3447 // n = nl >> pow 3448 n->op = ORSH; 3449 nodconst(nc, types[simtype[TUINT]], pow); 3450 } 3451 n->typecheck = 0; 3452 n->right = nc; 3453 break; 3454 } 3455 goto ret; 3456 3457 divbymul: 3458 // try to do division by multiply by (2^w)/d 3459 // see hacker's delight chapter 10 3460 // TODO: support 64-bit magic multiply here. 3461 m.w = w; 3462 if(issigned[nl->type->etype]) { 3463 m.sd = mpgetfix(nr->val.u.xval); 3464 smagic(&m); 3465 } else { 3466 m.ud = mpgetfix(nr->val.u.xval); 3467 umagic(&m); 3468 } 3469 if(m.bad) 3470 return; 3471 3472 // We have a quick division method so use it 3473 // for modulo too. 3474 if(n->op == OMOD) 3475 goto longmod; 3476 3477 switch(simtype[nl->type->etype]) { 3478 default: 3479 return; 3480 3481 case TUINT8: 3482 case TUINT16: 3483 case TUINT32: 3484 // n1 = nl * magic >> w (HMUL) 3485 nc = nod(OXXX, N, N); 3486 nodconst(nc, nl->type, m.um); 3487 n1 = nod(OMUL, nl, nc); 3488 typecheck(&n1, Erv); 3489 n1->op = OHMUL; 3490 if(m.ua) { 3491 // Select a Go type with (at least) twice the width. 3492 switch(simtype[nl->type->etype]) { 3493 default: 3494 return; 3495 case TUINT8: 3496 case TUINT16: 3497 twide = types[TUINT32]; 3498 break; 3499 case TUINT32: 3500 twide = types[TUINT64]; 3501 break; 3502 case TINT8: 3503 case TINT16: 3504 twide = types[TINT32]; 3505 break; 3506 case TINT32: 3507 twide = types[TINT64]; 3508 break; 3509 } 3510 3511 // add numerator (might overflow). 3512 // n2 = (n1 + nl) 3513 n2 = nod(OADD, conv(n1, twide), conv(nl, twide)); 3514 3515 // shift by m.s 3516 nc = nod(OXXX, N, N); 3517 nodconst(nc, types[TUINT], m.s); 3518 n = conv(nod(ORSH, n2, nc), nl->type); 3519 } else { 3520 // n = n1 >> m.s 3521 nc = nod(OXXX, N, N); 3522 nodconst(nc, types[TUINT], m.s); 3523 n = nod(ORSH, n1, nc); 3524 } 3525 break; 3526 3527 case TINT8: 3528 case TINT16: 3529 case TINT32: 3530 // n1 = nl * magic >> w 3531 nc = nod(OXXX, N, N); 3532 nodconst(nc, nl->type, m.sm); 3533 n1 = nod(OMUL, nl, nc); 3534 typecheck(&n1, Erv); 3535 n1->op = OHMUL; 3536 if(m.sm < 0) { 3537 // add the numerator. 3538 n1 = nod(OADD, n1, nl); 3539 } 3540 // shift by m.s 3541 nc = nod(OXXX, N, N); 3542 nodconst(nc, types[TUINT], m.s); 3543 n2 = conv(nod(ORSH, n1, nc), nl->type); 3544 // add 1 iff n1 is negative. 3545 nc = nod(OXXX, N, N); 3546 nodconst(nc, types[TUINT], w-1); 3547 n3 = nod(ORSH, nl, nc); // n4 = -1 iff n1 is negative. 3548 n = nod(OSUB, n2, n3); 3549 // apply sign. 3550 if(m.sd < 0) 3551 n = nod(OMINUS, n, N); 3552 break; 3553 } 3554 goto ret; 3555 3556 longmod: 3557 // rewrite as A%B = A - (A/B*B). 3558 n1 = nod(ODIV, nl, nr); 3559 n2 = nod(OMUL, n1, nr); 3560 n = nod(OSUB, nl, n2); 3561 goto ret; 3562 3563 ret: 3564 typecheck(&n, Erv); 3565 walkexpr(&n, init); 3566 *np = n; 3567 } 3568 3569 // return 1 if integer n must be in range [0, max), 0 otherwise 3570 static int 3571 bounded(Node *n, int64 max) 3572 { 3573 int64 v; 3574 int32 bits; 3575 int sign; 3576 3577 if(n->type == T || !isint[n->type->etype]) 3578 return 0; 3579 3580 sign = issigned[n->type->etype]; 3581 bits = 8*n->type->width; 3582 3583 if(smallintconst(n)) { 3584 v = mpgetfix(n->val.u.xval); 3585 return 0 <= v && v < max; 3586 } 3587 3588 switch(n->op) { 3589 case OAND: 3590 v = -1; 3591 if(smallintconst(n->left)) { 3592 v = mpgetfix(n->left->val.u.xval); 3593 } else if(smallintconst(n->right)) { 3594 v = mpgetfix(n->right->val.u.xval); 3595 } 3596 if(0 <= v && v < max) 3597 return 1; 3598 break; 3599 3600 case OMOD: 3601 if(!sign && smallintconst(n->right)) { 3602 v = mpgetfix(n->right->val.u.xval); 3603 if(0 <= v && v <= max) 3604 return 1; 3605 } 3606 break; 3607 3608 case ODIV: 3609 if(!sign && smallintconst(n->right)) { 3610 v = mpgetfix(n->right->val.u.xval); 3611 while(bits > 0 && v >= 2) { 3612 bits--; 3613 v >>= 1; 3614 } 3615 } 3616 break; 3617 3618 case ORSH: 3619 if(!sign && smallintconst(n->right)) { 3620 v = mpgetfix(n->right->val.u.xval); 3621 if(v > bits) 3622 return 1; 3623 bits -= v; 3624 } 3625 break; 3626 } 3627 3628 if(!sign && bits <= 62 && (1LL<<bits) <= max) 3629 return 1; 3630 3631 return 0; 3632 } 3633 3634 void 3635 usefield(Node *n) 3636 { 3637 Type *field, *l; 3638 3639 if(!fieldtrack_enabled) 3640 return; 3641 3642 switch(n->op) { 3643 default: 3644 fatal("usefield %O", n->op); 3645 case ODOT: 3646 case ODOTPTR: 3647 break; 3648 } 3649 3650 field = n->paramfld; 3651 if(field == T) 3652 fatal("usefield %T %S without paramfld", n->left->type, n->right->sym); 3653 if(field->note == nil || strstr(field->note->s, "go:\"track\"") == nil) 3654 return; 3655 3656 // dedup on list 3657 if(field->lastfn == curfn) 3658 return; 3659 field->lastfn = curfn; 3660 field->outer = n->left->type; 3661 if(isptr[field->outer->etype]) 3662 field->outer = field->outer->type; 3663 if(field->outer->sym == S) 3664 yyerror("tracked field must be in named struct type"); 3665 if(!exportname(field->sym->name)) 3666 yyerror("tracked field must be exported (upper case)"); 3667 3668 l = typ(0); 3669 l->type = field; 3670 l->down = curfn->paramfld; 3671 curfn->paramfld = l; 3672 } 3673 3674 static int 3675 candiscardlist(NodeList *l) 3676 { 3677 for(; l; l=l->next) 3678 if(!candiscard(l->n)) 3679 return 0; 3680 return 1; 3681 } 3682 3683 int 3684 candiscard(Node *n) 3685 { 3686 if(n == N) 3687 return 1; 3688 3689 switch(n->op) { 3690 default: 3691 return 0; 3692 3693 case ONAME: 3694 case ONONAME: 3695 case OTYPE: 3696 case OPACK: 3697 case OLITERAL: 3698 case OADD: 3699 case OSUB: 3700 case OOR: 3701 case OXOR: 3702 case OADDSTR: 3703 case OADDR: 3704 case OANDAND: 3705 case OARRAYBYTESTR: 3706 case OARRAYRUNESTR: 3707 case OSTRARRAYBYTE: 3708 case OSTRARRAYRUNE: 3709 case OCAP: 3710 case OCMPIFACE: 3711 case OCMPSTR: 3712 case OCOMPLIT: 3713 case OMAPLIT: 3714 case OSTRUCTLIT: 3715 case OARRAYLIT: 3716 case OPTRLIT: 3717 case OCONV: 3718 case OCONVIFACE: 3719 case OCONVNOP: 3720 case ODOT: 3721 case OEQ: 3722 case ONE: 3723 case OLT: 3724 case OLE: 3725 case OGT: 3726 case OGE: 3727 case OKEY: 3728 case OLEN: 3729 case OMUL: 3730 case OLSH: 3731 case ORSH: 3732 case OAND: 3733 case OANDNOT: 3734 case ONEW: 3735 case ONOT: 3736 case OCOM: 3737 case OPLUS: 3738 case OMINUS: 3739 case OOROR: 3740 case OPAREN: 3741 case ORUNESTR: 3742 case OREAL: 3743 case OIMAG: 3744 case OCOMPLEX: 3745 // Discardable as long as the subpieces are. 3746 break; 3747 3748 case ODIV: 3749 case OMOD: 3750 // Discardable as long as we know it's not division by zero. 3751 if(isconst(n->right, CTINT) && mpcmpfixc(n->right->val.u.xval, 0) != 0) 3752 break; 3753 if(isconst(n->right, CTFLT) && mpcmpfltc(n->right->val.u.fval, 0) != 0) 3754 break; 3755 return 0; 3756 3757 case OMAKECHAN: 3758 case OMAKEMAP: 3759 // Discardable as long as we know it won't fail because of a bad size. 3760 if(isconst(n->left, CTINT) && mpcmpfixc(n->left->val.u.xval, 0) == 0) 3761 break; 3762 return 0; 3763 3764 case OMAKESLICE: 3765 // Difficult to tell what sizes are okay. 3766 return 0; 3767 } 3768 3769 if(!candiscard(n->left) || 3770 !candiscard(n->right) || 3771 !candiscard(n->ntest) || 3772 !candiscard(n->nincr) || 3773 !candiscardlist(n->ninit) || 3774 !candiscardlist(n->nbody) || 3775 !candiscardlist(n->nelse) || 3776 !candiscardlist(n->list) || 3777 !candiscardlist(n->rlist)) { 3778 return 0; 3779 } 3780 3781 return 1; 3782 }