1 #include "gc.h" 2 3 void 4 cgen(Node *n, Node *nn) 5 { 6 Node *l, *r; 7 Prog *p1; 8 Node nod, nod1, nod2, nod3, nod4; 9 int o; 10 long v, curs; 11 12 if(debug['g']) { 13 prtree(nn, "cgen lhs"); 14 prtree(n, "cgen"); 15 } 16 if(n == Z || n->type == T) 17 return; 18 if(typecmplx[n->type->etype]) { 19 sugen(n, nn, n->type->width); 20 return; 21 } 22 l = n->left; 23 r = n->right; 24 o = n->op; 25 if(n->addable >= INDEXED) { 26 if(nn == Z) { 27 switch(o) { 28 default: 29 nullwarn(Z, Z); 30 break; 31 case OINDEX: 32 nullwarn(l, r); 33 break; 34 } 35 return; 36 } 37 gmove(n, nn); 38 return; 39 } 40 curs = cursafe; 41 42 if(n->complex >= FNX) 43 if(l->complex >= FNX) 44 if(r != Z && r->complex >= FNX) 45 switch(o) { 46 default: 47 regret(&nod, r); 48 cgen(r, &nod); 49 50 regsalloc(&nod1, r); 51 gopcode(OAS, &nod, Z, &nod1); 52 53 regfree(&nod); 54 nod = *n; 55 nod.right = &nod1; 56 cgen(&nod, nn); 57 return; 58 59 case OFUNC: 60 case OCOMMA: 61 case OANDAND: 62 case OOROR: 63 case OCOND: 64 case ODOT: 65 break; 66 } 67 68 switch(o) { 69 default: 70 diag(n, "unknown op in cgen: %O", o); 71 break; 72 73 case OAS: 74 if(l->op == OBIT) 75 goto bitas; 76 if(l->addable >= INDEXED && l->complex < FNX) { 77 if(nn != Z || r->addable < INDEXED) { 78 if(r->complex >= FNX && nn == Z) 79 regret(&nod, r); 80 else 81 regalloc(&nod, r, nn); 82 cgen(r, &nod); 83 gmove(&nod, l); 84 if(nn != Z) 85 gmove(&nod, nn); 86 regfree(&nod); 87 } else 88 gmove(r, l); 89 break; 90 } 91 if(l->complex >= r->complex) { 92 reglcgen(&nod1, l, Z); 93 if(r->addable >= INDEXED) { 94 gmove(r, &nod1); 95 if(nn != Z) 96 gmove(r, nn); 97 regfree(&nod1); 98 break; 99 } 100 regalloc(&nod, r, nn); 101 cgen(r, &nod); 102 } else { 103 regalloc(&nod, r, nn); 104 cgen(r, &nod); 105 reglcgen(&nod1, l, Z); 106 } 107 gmove(&nod, &nod1); 108 regfree(&nod); 109 regfree(&nod1); 110 break; 111 112 bitas: 113 n = l->left; 114 regalloc(&nod, r, nn); 115 if(l->complex >= r->complex) { 116 reglcgen(&nod1, n, Z); 117 cgen(r, &nod); 118 } else { 119 cgen(r, &nod); 120 reglcgen(&nod1, n, Z); 121 } 122 regalloc(&nod2, n, Z); 123 gopcode(OAS, &nod1, Z, &nod2); 124 bitstore(l, &nod, &nod1, &nod2, nn); 125 break; 126 127 case OBIT: 128 if(nn == Z) { 129 nullwarn(l, Z); 130 break; 131 } 132 bitload(n, &nod, Z, Z, nn); 133 gopcode(OAS, &nod, Z, nn); 134 regfree(&nod); 135 break; 136 137 case OADD: 138 case OSUB: 139 case OAND: 140 case OOR: 141 case OXOR: 142 case OLSHR: 143 case OASHL: 144 case OASHR: 145 /* 146 * immediate operands 147 */ 148 if(nn != Z) 149 if(sconst(r)) 150 if(!typefd[n->type->etype]) 151 if(r->vconst >= -2048 && r->vconst < 2048) { 152 cgen(l, nn); 153 if(r->vconst == 0) 154 if(o != OAND) 155 break; 156 if(nn != Z) 157 gopcode(o, r, Z, nn); 158 break; 159 } 160 161 case OLMUL: 162 case OLDIV: 163 case OLMOD: 164 case OMUL: 165 case ODIV: 166 case OMOD: 167 if(nn == Z) { 168 nullwarn(l, r); 169 break; 170 } 171 if(o == OMUL || o == OLMUL) { 172 if(mulcon(n, nn)) 173 break; 174 } 175 if(l->complex >= r->complex) { 176 regalloc(&nod, l, nn); 177 cgen(l, &nod); 178 regalloc(&nod1, r, Z); 179 cgen(r, &nod1); 180 gopcode(o, &nod1, Z, &nod); 181 } else { 182 regalloc(&nod, r, nn); 183 cgen(r, &nod); 184 regalloc(&nod1, l, Z); 185 cgen(l, &nod1); 186 gopcode(o, &nod, &nod1, &nod); 187 } 188 gopcode(OAS, &nod, Z, nn); 189 regfree(&nod); 190 regfree(&nod1); 191 break; 192 193 case OASLSHR: 194 case OASASHL: 195 case OASASHR: 196 case OASAND: 197 case OASADD: 198 case OASSUB: 199 case OASXOR: 200 case OASOR: 201 if(l->op == OBIT) 202 goto asbitop; 203 if(sconst(r)) 204 if(!typefd[n->type->etype]) { 205 if(l->addable < INDEXED) 206 reglcgen(&nod2, l, Z); 207 else 208 nod2 = *l; 209 regalloc(&nod, r, nn); 210 gopcode(OAS, &nod2, Z, &nod); 211 gopcode(o, r, Z, &nod); 212 gopcode(OAS, &nod, Z, &nod2); 213 214 regfree(&nod); 215 if(l->addable < INDEXED) 216 regfree(&nod2); 217 break; 218 } 219 220 case OASLMUL: 221 case OASLDIV: 222 case OASLMOD: 223 case OASMUL: 224 case OASDIV: 225 case OASMOD: 226 if(l->op == OBIT) 227 goto asbitop; 228 if(l->complex >= r->complex) { 229 if(l->addable < INDEXED) 230 reglcgen(&nod2, l, Z); 231 else 232 nod2 = *l; 233 regalloc(&nod1, r, Z); 234 cgen(r, &nod1); 235 } else { 236 regalloc(&nod1, r, Z); 237 cgen(r, &nod1); 238 if(l->addable < INDEXED) 239 reglcgen(&nod2, l, Z); 240 else 241 nod2 = *l; 242 } 243 244 regalloc(&nod, n, nn); 245 gmove(&nod2, &nod); 246 gopcode(o, &nod1, Z, &nod); 247 gmove(&nod, &nod2); 248 if(nn != Z) 249 gopcode(OAS, &nod, Z, nn); 250 regfree(&nod); 251 regfree(&nod1); 252 if(l->addable < INDEXED) 253 regfree(&nod2); 254 break; 255 256 asbitop: 257 regalloc(&nod4, n, nn); 258 if(l->complex >= r->complex) { 259 bitload(l, &nod, &nod1, &nod2, &nod4); 260 regalloc(&nod3, r, Z); 261 cgen(r, &nod3); 262 } else { 263 regalloc(&nod3, r, Z); 264 cgen(r, &nod3); 265 bitload(l, &nod, &nod1, &nod2, &nod4); 266 } 267 gmove(&nod, &nod4); 268 gopcode(o, &nod3, Z, &nod4); 269 regfree(&nod3); 270 gmove(&nod4, &nod); 271 regfree(&nod4); 272 bitstore(l, &nod, &nod1, &nod2, nn); 273 break; 274 275 case OADDR: 276 if(nn == Z) { 277 nullwarn(l, Z); 278 break; 279 } 280 lcgen(l, nn); 281 break; 282 283 case OFUNC: 284 if(l->complex >= FNX) { 285 if(l->op != OIND) 286 diag(n, "bad function call"); 287 288 regret(&nod, l->left); 289 cgen(l->left, &nod); 290 regsalloc(&nod1, l->left); 291 gopcode(OAS, &nod, Z, &nod1); 292 regfree(&nod); 293 294 nod = *n; 295 nod.left = &nod2; 296 nod2 = *l; 297 nod2.left = &nod1; 298 nod2.complex = 1; 299 cgen(&nod, nn); 300 301 return; 302 } 303 o = reg[REGARG]; 304 gargs(r, &nod, &nod1); 305 if(l->addable < INDEXED) { 306 reglcgen(&nod, l, Z); 307 gopcode(OFUNC, Z, Z, &nod); 308 regfree(&nod); 309 } else 310 gopcode(OFUNC, Z, Z, l); 311 if(REGARG) 312 if(o != reg[REGARG]) 313 reg[REGARG]--; 314 if(nn != Z) { 315 regret(&nod, n); 316 gopcode(OAS, &nod, Z, nn); 317 regfree(&nod); 318 } 319 break; 320 321 case OIND: 322 if(nn == Z) { 323 nullwarn(l, Z); 324 break; 325 } 326 regialloc(&nod, n, nn); 327 r = l; 328 while(r->op == OADD) 329 r = r->right; 330 if(sconst(r)) { 331 v = r->vconst; 332 r->vconst = 0; 333 cgen(l, &nod); 334 nod.xoffset += v; 335 r->vconst = v; 336 } else 337 cgen(l, &nod); 338 regind(&nod, n); 339 gopcode(OAS, &nod, Z, nn); 340 regfree(&nod); 341 break; 342 343 case OEQ: 344 case ONE: 345 case OLE: 346 case OLT: 347 case OGE: 348 case OGT: 349 case OLO: 350 case OLS: 351 case OHI: 352 case OHS: 353 if(nn == Z) { 354 nullwarn(l, r); 355 break; 356 } 357 boolgen(n, 1, nn); 358 break; 359 360 case OANDAND: 361 case OOROR: 362 boolgen(n, 1, nn); 363 if(nn == Z) 364 patch(p, pc); 365 break; 366 367 case ONOT: 368 if(nn == Z) { 369 nullwarn(l, Z); 370 break; 371 } 372 boolgen(n, 1, nn); 373 break; 374 375 case OCOMMA: 376 cgen(l, Z); 377 cgen(r, nn); 378 break; 379 380 case OCAST: 381 if(nn == Z) { 382 nullwarn(l, Z); 383 break; 384 } 385 /* 386 * convert from types l->n->nn 387 */ 388 if(nocast(l->type, n->type)) { 389 if(nocast(n->type, nn->type)) { 390 cgen(l, nn); 391 break; 392 } 393 } 394 regalloc(&nod, l, nn); 395 cgen(l, &nod); 396 #ifdef maybe 397 if(l->op == ONAME || l->op == OINDREG || l->op == OIND) 398 if(typechlp[l->type->etype] && typeilp[nn->type->etype]){ 399 /* load effectively does the cast */ 400 nod.type = types[TLONG]; 401 gopcode(OAS, &nod, Z, nn); 402 regfree(&nod); 403 break; 404 } 405 #endif 406 regalloc(&nod1, n, &nod); 407 gopcode(OAS, &nod, Z, &nod1); 408 gopcode(OAS, &nod1, Z, nn); 409 regfree(&nod1); 410 regfree(&nod); 411 break; 412 413 case ODOT: 414 sugen(l, nodrat, l->type->width); 415 if(nn != Z) { 416 warn(n, "non-interruptable temporary"); 417 nod = *nodrat; 418 if(!r || r->op != OCONST) { 419 diag(n, "DOT and no offset"); 420 break; 421 } 422 nod.xoffset += (long)r->vconst; 423 nod.type = n->type; 424 cgen(&nod, nn); 425 } 426 break; 427 428 case OCOND: 429 bcgen(l, 1); 430 p1 = p; 431 cgen(r->left, nn); 432 gbranch(OGOTO); 433 patch(p1, pc); 434 p1 = p; 435 cgen(r->right, nn); 436 patch(p1, pc); 437 break; 438 439 case OPOSTINC: 440 case OPOSTDEC: 441 v = 1; 442 if(l->type->etype == TIND) 443 v = l->type->link->width; 444 if(o == OPOSTDEC) 445 v = -v; 446 if(l->op == OBIT) 447 goto bitinc; 448 if(nn == Z) 449 goto pre; 450 451 if(l->addable < INDEXED) 452 reglcgen(&nod2, l, Z); 453 else 454 nod2 = *l; 455 456 regalloc(&nod, l, nn); 457 gopcode(OAS, &nod2, Z, &nod); 458 regalloc(&nod1, l, Z); 459 if(typefd[l->type->etype]) { 460 regalloc(&nod3, l, Z); 461 if(v < 0) { 462 gopcode(OAS, nodfconst(-v), Z, &nod3); 463 gopcode(OSUB, &nod3, &nod, &nod1); 464 } else { 465 gopcode(OAS, nodfconst(v), Z, &nod3); 466 gopcode(OADD, &nod3, &nod, &nod1); 467 } 468 regfree(&nod3); 469 } else 470 gopcode(OADD, nodconst(v), &nod, &nod1); 471 gopcode(OAS, &nod1, Z, &nod2); 472 473 regfree(&nod); 474 regfree(&nod1); 475 if(l->addable < INDEXED) 476 regfree(&nod2); 477 break; 478 479 case OPREINC: 480 case OPREDEC: 481 v = 1; 482 if(l->type->etype == TIND) 483 v = l->type->link->width; 484 if(o == OPREDEC) 485 v = -v; 486 if(l->op == OBIT) 487 goto bitinc; 488 489 pre: 490 if(l->addable < INDEXED) 491 reglcgen(&nod2, l, Z); 492 else 493 nod2 = *l; 494 495 regalloc(&nod, l, nn); 496 gopcode(OAS, &nod2, Z, &nod); 497 if(typefd[l->type->etype]) { 498 regalloc(&nod3, l, Z); 499 if(v < 0) { 500 gopcode(OAS, nodfconst(-v), Z, &nod3); 501 gopcode(OSUB, &nod3, Z, &nod); 502 } else { 503 gopcode(OAS, nodfconst(v), Z, &nod3); 504 gopcode(OADD, &nod3, Z, &nod); 505 } 506 regfree(&nod3); 507 } else 508 gopcode(OADD, nodconst(v), Z, &nod); 509 gopcode(OAS, &nod, Z, &nod2); 510 if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ 511 gins(ANOP, l, Z); 512 513 regfree(&nod); 514 if(l->addable < INDEXED) 515 regfree(&nod2); 516 break; 517 518 bitinc: 519 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 520 bitload(l, &nod, &nod1, &nod2, Z); 521 gopcode(OAS, &nod, Z, nn); 522 gopcode(OADD, nodconst(v), Z, &nod); 523 bitstore(l, &nod, &nod1, &nod2, Z); 524 break; 525 } 526 bitload(l, &nod, &nod1, &nod2, nn); 527 gopcode(OADD, nodconst(v), Z, &nod); 528 bitstore(l, &nod, &nod1, &nod2, nn); 529 break; 530 } 531 cursafe = curs; 532 } 533 534 void 535 reglcgen(Node *t, Node *n, Node *nn) 536 { 537 Node *r; 538 long v; 539 540 regialloc(t, n, nn); 541 if(n->op == OIND) { 542 r = n->left; 543 while(r->op == OADD) 544 r = r->right; 545 if(sconst(r)) { 546 v = r->vconst; 547 r->vconst = 0; 548 lcgen(n, t); 549 t->xoffset += v; 550 r->vconst = v; 551 regind(t, n); 552 return; 553 } 554 } 555 lcgen(n, t); 556 regind(t, n); 557 } 558 559 void 560 lcgen(Node *n, Node *nn) 561 { 562 Prog *p1; 563 Node nod; 564 565 if(debug['g']) { 566 prtree(nn, "lcgen lhs"); 567 prtree(n, "lcgen"); 568 } 569 if(n == Z || n->type == T) 570 return; 571 if(nn == Z) { 572 nn = &nod; 573 regalloc(&nod, n, Z); 574 } 575 switch(n->op) { 576 default: 577 if(n->addable < INDEXED) { 578 diag(n, "unknown op in lcgen: %O", n->op); 579 break; 580 } 581 nod = *n; 582 nod.op = OADDR; 583 nod.left = n; 584 nod.right = Z; 585 nod.type = types[TIND]; 586 gopcode(OAS, &nod, Z, nn); 587 break; 588 589 case OCOMMA: 590 cgen(n->left, n->left); 591 lcgen(n->right, nn); 592 break; 593 594 case OIND: 595 cgen(n->left, nn); 596 break; 597 598 case OCOND: 599 bcgen(n->left, 1); 600 p1 = p; 601 lcgen(n->right->left, nn); 602 gbranch(OGOTO); 603 patch(p1, pc); 604 p1 = p; 605 lcgen(n->right->right, nn); 606 patch(p1, pc); 607 break; 608 } 609 } 610 611 /* 612 * Conditional branch if bool(n) != true 613 */ 614 void 615 bcgen(Node *n, int true) 616 { 617 618 if(n->type == T) 619 gbranch(OGOTO); 620 else 621 boolgen(n, true, Z); 622 } 623 624 /* 625 * If nn == Z, conditional branch if bool(n) != true 626 * If nn != Z, assign n = (bool(n) == true) 627 */ 628 void 629 boolgen(Node *n, int true, Node *nn) 630 { 631 int o; 632 Prog *p1, *p2; 633 Node *l, *r, nod, nod1, nod2; 634 long curs; 635 636 if(debug['g']) { 637 prtree(nn, "boolgen lhs"); 638 prtree(n, true? "boolgen true" : "boolgen false"); 639 } 640 curs = cursafe; 641 l = n->left; 642 r = n->right; 643 switch(n->op) { 644 645 default: 646 regalloc(&nod, n, nn); 647 cgen(n, &nod); 648 if(nn == Z) { 649 o = true? OEQ : ONE; 650 if(typefd[n->type->etype]) { 651 nodreg(&nod1, n, NREG+FREGZERO); 652 gopcode(o, &nod, &nod1, Z); 653 } else 654 gopcode(o, &nod, Z, Z); 655 regfree(&nod); 656 break; 657 } 658 if(typefd[n->type->etype]) { 659 regalloc(&nod2, nn, nn); 660 o = true? ONE : OEQ; 661 nodreg(&nod1, n, NREG+FREGZERO); 662 gopcode(o, &nod, &nod1, &nod2); 663 gopcode(OAS, &nod2, Z, nn); 664 regfree(&nod2); 665 regfree(&nod); 666 break; 667 } 668 if(true) 669 gopcode(OCOND, &nod, nodconst(0), &nod); 670 else 671 gopcode(OCOND, nodconst(1), &nod, &nod); 672 gopcode(OAS, &nod, Z, nn); 673 regfree(&nod); 674 break; 675 676 case OCONST: 677 o = vconst(n); 678 if(!true) 679 o = !o; 680 gbranch(OGOTO); 681 if(o) { 682 p1 = p; 683 gbranch(OGOTO); 684 patch(p1, pc); 685 } 686 goto com; 687 688 case OCOMMA: 689 cgen(l, Z); 690 boolgen(r, true, nn); 691 break; 692 693 case ONOT: 694 boolgen(l, !true, nn); 695 break; 696 697 case OCOND: 698 bcgen(l, 1); 699 p1 = p; 700 bcgen(r->left, true); 701 p2 = p; 702 gbranch(OGOTO); 703 patch(p1, pc); 704 p1 = p; 705 bcgen(r->right, !true); 706 patch(p2, pc); 707 p2 = p; 708 gbranch(OGOTO); 709 patch(p1, pc); 710 patch(p2, pc); 711 goto com; 712 713 case OANDAND: 714 if(!true) 715 goto caseor; 716 717 caseand: 718 bcgen(l, true); 719 p1 = p; 720 bcgen(r, !true); 721 p2 = p; 722 patch(p1, pc); 723 gbranch(OGOTO); 724 patch(p2, pc); 725 goto com; 726 727 case OOROR: 728 if(!true) 729 goto caseand; 730 731 caseor: 732 bcgen(l, !true); 733 p1 = p; 734 bcgen(r, !true); 735 p2 = p; 736 gbranch(OGOTO); 737 patch(p1, pc); 738 patch(p2, pc); 739 goto com; 740 741 case OEQ: 742 case ONE: 743 case OLE: 744 case OLT: 745 case OGE: 746 case OGT: 747 case OHI: 748 case OHS: 749 case OLO: 750 case OLS: 751 o = n->op; 752 if(l->complex >= FNX && r->complex >= FNX) { 753 regret(&nod, r); 754 cgen(r, &nod); 755 regsalloc(&nod1, r); 756 gopcode(OAS, &nod, Z, &nod1); 757 regfree(&nod); 758 nod = *n; 759 nod.right = &nod1; 760 boolgen(&nod, true, nn); 761 break; 762 } 763 if(true) 764 o = comrel[relindex(o)]; 765 if(nn != Z || typefd[l->type->etype]) { 766 if(l->complex >= r->complex) { 767 regalloc(&nod1, l, nn); 768 cgen(l, &nod1); 769 regalloc(&nod, r, Z); 770 cgen(r, &nod); 771 } else { 772 regalloc(&nod, r, nn); 773 cgen(r, &nod); 774 regalloc(&nod1, l, Z); 775 cgen(l, &nod1); 776 } 777 if(typefd[l->type->etype]) { 778 if(nn != Z) { 779 /* fp compare for assignment */ 780 regalloc(&nod2, nn, nn); 781 gopcode(o, &nod, &nod1, &nod2); 782 regfree(&nod2); 783 } else 784 /* fp compare for branch */ 785 gopcode(o, &nod, &nod1, Z); 786 regfree(&nod); 787 regfree(&nod1); 788 break; 789 } 790 /* int compare for assignment */ 791 switch(o) { 792 case OEQ: 793 gopcode(OSUB, &nod1, &nod, &nod); 794 gopcode(OCOND, &nod, nodconst(0), &nod); 795 break; 796 case ONE: 797 gopcode(OSUB, &nod1, &nod, &nod); 798 gopcode(OCOND, nodconst(1), &nod, &nod); 799 break; 800 case OLE: 801 gopcode(OCOMMA, &nod1, &nod, &nod); 802 break; 803 case OGT: 804 gopcode(OCOMMA, &nod1, &nod, &nod); 805 gopcode(OXOR, nodconst(1), &nod, &nod); 806 break; 807 case OLT: 808 gopcode(OCOMMA, &nod, &nod1, &nod); 809 gopcode(OXOR, nodconst(1), &nod, &nod); 810 break; 811 case OGE: 812 gopcode(OCOMMA, &nod, &nod1, &nod); 813 break; 814 case OLS: 815 gopcode(OCOND, &nod1, &nod, &nod); 816 break; 817 case OHI: 818 gopcode(OCOND, &nod1, &nod, &nod); 819 gopcode(OXOR, nodconst(1), &nod, &nod); 820 break; 821 case OLO: 822 gopcode(OCOND, &nod, &nod1, &nod); 823 gopcode(OXOR, nodconst(1), &nod, &nod); 824 break; 825 case OHS: 826 gopcode(OCOND, &nod, &nod1, &nod); 827 break; 828 } 829 gopcode(OAS, &nod, Z, nn); 830 regfree(&nod); 831 regfree(&nod1); 832 break; 833 } 834 /* int compare for branch */ 835 if(0 && sconst(l)) { 836 if(l->vconst == 0) { 837 regalloc(&nod, r, nn); 838 cgen(r, &nod); 839 gopcode(o, l, &nod, Z); 840 regfree(&nod); 841 goto com; 842 } 843 } 844 if(0 && sconst(r)) { 845 if(r->vconst == 0) { 846 regalloc(&nod, l, nn); 847 cgen(l, &nod); 848 gopcode(o, &nod, r, Z); 849 regfree(&nod); 850 goto com; 851 } 852 } 853 if(l->complex >= r->complex) { 854 regalloc(&nod1, l, nn); 855 cgen(l, &nod1); 856 regalloc(&nod, r, Z); 857 cgen(r, &nod); 858 } else { 859 regalloc(&nod, r, nn); 860 cgen(r, &nod); 861 regalloc(&nod1, l, Z); 862 cgen(l, &nod1); 863 } 864 865 gopcode(o, &nod, &nod1, Z); 866 regfree(&nod); 867 regfree(&nod1); 868 869 com: 870 if(nn != Z) { 871 p1 = p; 872 gopcode(OAS, nodconst(1), Z, nn); 873 gbranch(OGOTO); 874 p2 = p; 875 patch(p1, pc); 876 gopcode(OAS, nodconst(0), Z, nn); 877 patch(p2, pc); 878 } 879 break; 880 } 881 cursafe = curs; 882 } 883 884 void 885 sugen(Node *n, Node *nn, long w) 886 { 887 Prog *p1; 888 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 889 Type *t; 890 long pc1; 891 int i, m, c; 892 893 if(n == Z || n->type == T) 894 return; 895 if(debug['g']) { 896 prtree(nn, "sugen lhs"); 897 prtree(n, "sugen"); 898 } 899 if(nn == nodrat) 900 if(w > nrathole) 901 nrathole = w; 902 switch(n->op) { 903 case OIND: 904 if(nn == Z) { 905 nullwarn(n->left, Z); 906 break; 907 } 908 909 default: 910 goto copy; 911 912 case OCONST: 913 if(n->type && typev[n->type->etype]) { 914 if(nn == Z) { 915 nullwarn(n->left, Z); 916 break; 917 } 918 919 t = nn->type; 920 nn->type = types[TLONG]; 921 reglcgen(&nod1, nn, Z); 922 nn->type = t; 923 924 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 925 nod1.xoffset += SZ_LONG; 926 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 927 928 regfree(&nod1); 929 break; 930 } 931 goto copy; 932 933 case ODOT: 934 l = n->left; 935 sugen(l, nodrat, l->type->width); 936 if(nn != Z) { 937 warn(n, "non-interruptable temporary"); 938 nod1 = *nodrat; 939 r = n->right; 940 if(!r || r->op != OCONST) { 941 diag(n, "DOT and no offset"); 942 break; 943 } 944 nod1.xoffset += (long)r->vconst; 945 nod1.type = n->type; 946 sugen(&nod1, nn, w); 947 } 948 break; 949 950 case OSTRUCT: 951 /* 952 * rewrite so lhs has no fn call 953 */ 954 if(nn != Z && nn->complex >= FNX) { 955 nod1 = *n; 956 nod1.type = typ(TIND, n->type); 957 regret(&nod2, &nod1); 958 lcgen(nn, &nod2); 959 regsalloc(&nod0, &nod1); 960 gopcode(OAS, &nod2, Z, &nod0); 961 regfree(&nod2); 962 963 nod1 = *n; 964 nod1.op = OIND; 965 nod1.left = &nod0; 966 nod1.right = Z; 967 nod1.complex = 1; 968 969 sugen(n, &nod1, w); 970 return; 971 } 972 973 r = n->left; 974 for(t = n->type->link; t != T; t = t->down) { 975 l = r; 976 if(r->op == OLIST) { 977 l = r->left; 978 r = r->right; 979 } 980 if(nn == Z) { 981 cgen(l, nn); 982 continue; 983 } 984 /* 985 * hand craft *(&nn + o) = l 986 */ 987 nod0 = znode; 988 nod0.op = OAS; 989 nod0.type = t; 990 nod0.left = &nod1; 991 nod0.right = l; 992 993 nod1 = znode; 994 nod1.op = OIND; 995 nod1.type = t; 996 nod1.left = &nod2; 997 998 nod2 = znode; 999 nod2.op = OADD; 1000 nod2.type = typ(TIND, t); 1001 nod2.left = &nod3; 1002 nod2.right = &nod4; 1003 1004 nod3 = znode; 1005 nod3.op = OADDR; 1006 nod3.type = nod2.type; 1007 nod3.left = nn; 1008 1009 nod4 = znode; 1010 nod4.op = OCONST; 1011 nod4.type = nod2.type; 1012 nod4.vconst = t->offset; 1013 1014 ccom(&nod0); 1015 acom(&nod0); 1016 xcom(&nod0); 1017 nod0.addable = 0; 1018 1019 cgen(&nod0, Z); 1020 } 1021 break; 1022 1023 case OAS: 1024 if(nn == Z) { 1025 if(n->addable < INDEXED) 1026 sugen(n->right, n->left, w); 1027 break; 1028 } 1029 sugen(n->right, nodrat, w); 1030 warn(n, "non-interruptable temporary"); 1031 sugen(nodrat, n->left, w); 1032 sugen(nodrat, nn, w); 1033 break; 1034 1035 case OFUNC: 1036 if(nn == Z) { 1037 sugen(n, nodrat, w); 1038 break; 1039 } 1040 if(nn->op != OIND) { 1041 nn = new1(OADDR, nn, Z); 1042 nn->type = types[TIND]; 1043 nn->addable = 0; 1044 } else 1045 nn = nn->left; 1046 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 1047 n->type = types[TVOID]; 1048 n->left->type = types[TVOID]; 1049 cgen(n, Z); 1050 break; 1051 1052 case OCOND: 1053 bcgen(n->left, 1); 1054 p1 = p; 1055 sugen(n->right->left, nn, w); 1056 gbranch(OGOTO); 1057 patch(p1, pc); 1058 p1 = p; 1059 sugen(n->right->right, nn, w); 1060 patch(p1, pc); 1061 break; 1062 1063 case OCOMMA: 1064 cgen(n->left, Z); 1065 sugen(n->right, nn, w); 1066 break; 1067 } 1068 return; 1069 1070 copy: 1071 if(nn == Z) 1072 return; 1073 if(n->complex >= FNX && nn->complex >= FNX) { 1074 t = nn->type; 1075 nn->type = types[TLONG]; 1076 regialloc(&nod1, nn, Z); 1077 lcgen(nn, &nod1); 1078 regsalloc(&nod2, nn); 1079 nn->type = t; 1080 1081 gopcode(OAS, &nod1, Z, &nod2); 1082 regfree(&nod1); 1083 1084 nod2.type = typ(TIND, t); 1085 1086 nod1 = nod2; 1087 nod1.op = OIND; 1088 nod1.left = &nod2; 1089 nod1.right = Z; 1090 nod1.complex = 1; 1091 nod1.type = t; 1092 1093 sugen(n, &nod1, w); 1094 return; 1095 } 1096 1097 if(n->complex > nn->complex) { 1098 t = n->type; 1099 n->type = types[TLONG]; 1100 reglcgen(&nod1, n, Z); 1101 n->type = t; 1102 1103 t = nn->type; 1104 nn->type = types[TLONG]; 1105 reglcgen(&nod2, nn, Z); 1106 nn->type = t; 1107 } else { 1108 t = nn->type; 1109 nn->type = types[TLONG]; 1110 reglcgen(&nod2, nn, Z); 1111 nn->type = t; 1112 1113 t = n->type; 1114 n->type = types[TLONG]; 1115 reglcgen(&nod1, n, Z); 1116 n->type = t; 1117 } 1118 1119 w /= SZ_LONG; 1120 if(w <= 5) { 1121 layout(&nod1, &nod2, w, 0, Z); 1122 goto out; 1123 } 1124 1125 /* 1126 * minimize space for unrolling loop 1127 * 3,4,5 times. (6 or more is never minimum) 1128 * if small structure, try 2 also. 1129 */ 1130 c = 0; /* set */ 1131 m = 100; 1132 i = 3; 1133 if(w <= 15) 1134 i = 2; 1135 for(; i<=5; i++) 1136 if(i + w%i <= m) { 1137 c = i; 1138 m = c + w%c; 1139 } 1140 1141 regalloc(&nod3, ®node, Z); 1142 layout(&nod1, &nod2, w%c, w/c, &nod3); 1143 1144 pc1 = pc; 1145 layout(&nod1, &nod2, c, 0, Z); 1146 1147 gopcode(OSUB, nodconst(1), Z, &nod3); 1148 nod1.op = OREGISTER; 1149 nod1.type = types[TIND]; 1150 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1); 1151 nod2.op = OREGISTER; 1152 nod2.type = types[TIND]; 1153 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2); 1154 1155 gopcode(OEQ, &nod3, Z, Z); 1156 p->as = ABGT; 1157 patch(p, pc1); 1158 1159 regfree(&nod3); 1160 out: 1161 regfree(&nod1); 1162 regfree(&nod2); 1163 } 1164 1165 void 1166 layout(Node *f, Node *t, int c, int cv, Node *cn) 1167 { 1168 Node t1, t2; 1169 1170 while(c > 3) { 1171 layout(f, t, 2, 0, Z); 1172 c -= 2; 1173 } 1174 1175 regalloc(&t1, ®node, Z); 1176 regalloc(&t2, ®node, Z); 1177 t1.type = types[TLONG]; 1178 t2.type = types[TLONG]; 1179 if(c > 0) { 1180 gopcode(OAS, f, Z, &t1); 1181 f->xoffset += SZ_LONG; 1182 } 1183 if(cn != Z) 1184 gopcode(OAS, nodconst(cv), Z, cn); 1185 if(c > 1) { 1186 gopcode(OAS, f, Z, &t2); 1187 f->xoffset += SZ_LONG; 1188 } 1189 if(c > 0) { 1190 gopcode(OAS, &t1, Z, t); 1191 t->xoffset += SZ_LONG; 1192 } 1193 if(c > 2) { 1194 gopcode(OAS, f, Z, &t1); 1195 f->xoffset += SZ_LONG; 1196 } 1197 if(c > 1) { 1198 gopcode(OAS, &t2, Z, t); 1199 t->xoffset += SZ_LONG; 1200 } 1201 if(c > 2) { 1202 gopcode(OAS, &t1, Z, t); 1203 t->xoffset += SZ_LONG; 1204 } 1205 regfree(&t1); 1206 regfree(&t2); 1207 } 1208