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