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