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