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(typesuv[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(r->op == OCONST) 150 if(!typefd[n->type->etype]) { 151 cgen(l, nn); 152 if(r->vconst == 0) 153 if(o != OAND) 154 break; 155 if(nn != Z) 156 gopcode(o, r, Z, nn); 157 break; 158 } 159 160 case OLMUL: 161 case OMUL: 162 case OLDIV: 163 case OLMOD: 164 case ODIV: 165 case OMOD: 166 if(nn == Z) { 167 nullwarn(l, r); 168 break; 169 } 170 if(o == OMUL || o == OLMUL) { 171 if(mulcon(n, nn)) 172 break; 173 } 174 if(l->complex >= r->complex) { 175 regalloc(&nod, l, nn); 176 cgen(l, &nod); 177 regalloc(&nod1, r, Z); 178 cgen(r, &nod1); 179 gopcode(o, &nod1, Z, &nod); 180 } else { 181 regalloc(&nod, r, nn); 182 cgen(r, &nod); 183 regalloc(&nod1, l, Z); 184 cgen(l, &nod1); 185 gopcode(o, &nod, &nod1, &nod); 186 } 187 gopcode(OAS, &nod, Z, nn); 188 regfree(&nod); 189 regfree(&nod1); 190 break; 191 192 case OASLSHR: 193 case OASASHL: 194 case OASASHR: 195 case OASAND: 196 case OASADD: 197 case OASSUB: 198 case OASXOR: 199 case OASOR: 200 if(l->op == OBIT) 201 goto asbitop; 202 if(r->op == OCONST) 203 if(!typefd[n->type->etype]) { 204 if(l->addable < INDEXED) 205 reglcgen(&nod2, l, Z); 206 else 207 nod2 = *l; 208 regalloc(&nod, r, nn); 209 gopcode(OAS, &nod2, Z, &nod); 210 gopcode(o, r, Z, &nod); 211 gopcode(OAS, &nod, Z, &nod2); 212 213 regfree(&nod); 214 if(l->addable < INDEXED) 215 regfree(&nod2); 216 break; 217 } 218 219 case OASLMUL: 220 case OASLDIV: 221 case OASLMOD: 222 case OASMUL: 223 case OASDIV: 224 case OASMOD: 225 if(l->op == OBIT) 226 goto asbitop; 227 if(l->complex >= r->complex) { 228 if(l->addable < INDEXED) 229 reglcgen(&nod2, l, Z); 230 else 231 nod2 = *l; 232 regalloc(&nod1, r, Z); 233 cgen(r, &nod1); 234 } else { 235 regalloc(&nod1, r, Z); 236 cgen(r, &nod1); 237 if(l->addable < INDEXED) 238 reglcgen(&nod2, l, Z); 239 else 240 nod2 = *l; 241 } 242 243 regalloc(&nod, n, nn); 244 gmove(&nod2, &nod); 245 gopcode(o, &nod1, Z, &nod); 246 gmove(&nod, &nod2); 247 if(nn != Z) 248 gopcode(OAS, &nod, Z, nn); 249 regfree(&nod); 250 regfree(&nod1); 251 if(l->addable < INDEXED) 252 regfree(&nod2); 253 break; 254 255 asbitop: 256 regalloc(&nod4, n, nn); 257 if(l->complex >= r->complex) { 258 bitload(l, &nod, &nod1, &nod2, &nod4); 259 regalloc(&nod3, r, Z); 260 cgen(r, &nod3); 261 } else { 262 regalloc(&nod3, r, Z); 263 cgen(r, &nod3); 264 bitload(l, &nod, &nod1, &nod2, &nod4); 265 } 266 gmove(&nod, &nod4); 267 gopcode(o, &nod3, Z, &nod4); 268 regfree(&nod3); 269 gmove(&nod4, &nod); 270 regfree(&nod4); 271 bitstore(l, &nod, &nod1, &nod2, nn); 272 break; 273 274 case OADDR: 275 if(nn == Z) { 276 nullwarn(l, Z); 277 break; 278 } 279 lcgen(l, nn); 280 break; 281 282 case OFUNC: 283 if(l->complex >= FNX) { 284 if(l->op != OIND) 285 diag(n, "bad function call"); 286 287 regret(&nod, l->left); 288 cgen(l->left, &nod); 289 regsalloc(&nod1, l->left); 290 gopcode(OAS, &nod, Z, &nod1); 291 regfree(&nod); 292 293 nod = *n; 294 nod.left = &nod2; 295 nod2 = *l; 296 nod2.left = &nod1; 297 nod2.complex = 1; 298 cgen(&nod, nn); 299 300 return; 301 } 302 o = reg[REGARG]; 303 gargs(r, &nod, &nod1); 304 if(l->addable < INDEXED) { 305 reglcgen(&nod, l, Z); 306 gopcode(OFUNC, Z, Z, &nod); 307 regfree(&nod); 308 } else 309 gopcode(OFUNC, Z, Z, l); 310 if(REGARG) 311 if(o != reg[REGARG]) 312 reg[REGARG]--; 313 if(nn != Z) { 314 regret(&nod, n); 315 gopcode(OAS, &nod, Z, nn); 316 regfree(&nod); 317 } 318 break; 319 320 case OIND: 321 if(nn == Z) { 322 nullwarn(l, Z); 323 break; 324 } 325 regialloc(&nod, n, nn); 326 r = l; 327 while(r->op == OADD) 328 r = r->right; 329 if(sconst(r)) { 330 v = r->vconst; 331 r->vconst = 0; 332 cgen(l, &nod); 333 nod.xoffset += v; 334 r->vconst = v; 335 } else 336 cgen(l, &nod); 337 regind(&nod, n); 338 gopcode(OAS, &nod, Z, nn); 339 regfree(&nod); 340 break; 341 342 case OEQ: 343 case ONE: 344 case OLE: 345 case OLT: 346 case OGE: 347 case OGT: 348 case OLO: 349 case OLS: 350 case OHI: 351 case OHS: 352 if(nn == Z) { 353 nullwarn(l, r); 354 break; 355 } 356 boolgen(n, 1, nn); 357 break; 358 359 case OANDAND: 360 case OOROR: 361 boolgen(n, 1, nn); 362 if(nn == Z) 363 patch(p, pc); 364 break; 365 366 case ONOT: 367 if(nn == Z) { 368 nullwarn(l, Z); 369 break; 370 } 371 boolgen(n, 1, nn); 372 break; 373 374 case OCOMMA: 375 cgen(l, Z); 376 cgen(r, nn); 377 break; 378 379 case OCAST: 380 if(nn == Z) { 381 nullwarn(l, Z); 382 break; 383 } 384 /* 385 * convert from types l->n->nn 386 */ 387 if(nocast(l->type, n->type)) { 388 if(nocast(n->type, nn->type)) { 389 cgen(l, nn); 390 break; 391 } 392 } 393 regalloc(&nod, l, nn); 394 cgen(l, &nod); 395 regalloc(&nod1, n, &nod); 396 gopcode(OAS, &nod, Z, &nod1); 397 gopcode(OAS, &nod1, Z, nn); 398 regfree(&nod1); 399 regfree(&nod); 400 break; 401 402 case ODOT: 403 sugen(l, nodrat, l->type->width); 404 if(nn != Z) { 405 warn(n, "non-interruptable temporary"); 406 nod = *nodrat; 407 if(!r || r->op != OCONST) { 408 diag(n, "DOT and no offset"); 409 break; 410 } 411 nod.xoffset += (long)r->vconst; 412 nod.type = n->type; 413 cgen(&nod, nn); 414 } 415 break; 416 417 case OCOND: 418 bcgen(l, 1); 419 p1 = p; 420 cgen(r->left, nn); 421 gbranch(OGOTO); 422 patch(p1, pc); 423 p1 = p; 424 cgen(r->right, nn); 425 patch(p1, pc); 426 break; 427 428 case OPOSTINC: 429 case OPOSTDEC: 430 v = 1; 431 if(l->type->etype == TIND) 432 v = l->type->link->width; 433 if(o == OPOSTDEC) 434 v = -v; 435 if(l->op == OBIT) 436 goto bitinc; 437 if(nn == Z) 438 goto pre; 439 440 if(l->addable < INDEXED) 441 reglcgen(&nod2, l, Z); 442 else 443 nod2 = *l; 444 445 regalloc(&nod, l, nn); 446 gopcode(OAS, &nod2, Z, &nod); 447 regalloc(&nod1, l, Z); 448 if(typefd[l->type->etype]) { 449 regalloc(&nod3, l, Z); 450 if(v < 0) { 451 gopcode(OAS, nodfconst(-v), Z, &nod3); 452 gopcode(OSUB, &nod3, &nod, &nod1); 453 } else { 454 gopcode(OAS, nodfconst(v), Z, &nod3); 455 gopcode(OADD, &nod3, &nod, &nod1); 456 } 457 regfree(&nod3); 458 } else 459 gopcode(OADD, nodconst(v), &nod, &nod1); 460 gopcode(OAS, &nod1, Z, &nod2); 461 462 regfree(&nod); 463 regfree(&nod1); 464 if(l->addable < INDEXED) 465 regfree(&nod2); 466 break; 467 468 case OPREINC: 469 case OPREDEC: 470 v = 1; 471 if(l->type->etype == TIND) 472 v = l->type->link->width; 473 if(o == OPREDEC) 474 v = -v; 475 if(l->op == OBIT) 476 goto bitinc; 477 478 pre: 479 if(l->addable < INDEXED) 480 reglcgen(&nod2, l, Z); 481 else 482 nod2 = *l; 483 484 regalloc(&nod, l, nn); 485 gopcode(OAS, &nod2, Z, &nod); 486 if(typefd[l->type->etype]) { 487 regalloc(&nod3, l, Z); 488 if(v < 0) { 489 gopcode(OAS, nodfconst(-v), Z, &nod3); 490 gopcode(OSUB, &nod3, Z, &nod); 491 } else { 492 gopcode(OAS, nodfconst(v), Z, &nod3); 493 gopcode(OADD, &nod3, Z, &nod); 494 } 495 regfree(&nod3); 496 } else 497 gopcode(OADD, nodconst(v), Z, &nod); 498 gopcode(OAS, &nod, Z, &nod2); 499 500 regfree(&nod); 501 if(l->addable < INDEXED) 502 regfree(&nod2); 503 break; 504 505 bitinc: 506 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 507 bitload(l, &nod, &nod1, &nod2, Z); 508 gopcode(OAS, &nod, Z, nn); 509 gopcode(OADD, nodconst(v), Z, &nod); 510 bitstore(l, &nod, &nod1, &nod2, Z); 511 break; 512 } 513 bitload(l, &nod, &nod1, &nod2, nn); 514 gopcode(OADD, nodconst(v), Z, &nod); 515 bitstore(l, &nod, &nod1, &nod2, nn); 516 break; 517 } 518 cursafe = curs; 519 } 520 521 void 522 reglcgen(Node *t, Node *n, Node *nn) 523 { 524 Node *r; 525 long v; 526 527 regialloc(t, n, nn); 528 if(n->op == OIND) { 529 r = n->left; 530 while(r->op == OADD) 531 r = r->right; 532 if(sconst(r)) { 533 v = r->vconst; 534 r->vconst = 0; 535 lcgen(n, t); 536 t->xoffset += v; 537 r->vconst = v; 538 regind(t, n); 539 return; 540 } 541 } 542 lcgen(n, t); 543 regind(t, n); 544 } 545 546 void 547 lcgen(Node *n, Node *nn) 548 { 549 Prog *p1; 550 Node nod; 551 552 if(debug['g']) { 553 prtree(nn, "lcgen lhs"); 554 prtree(n, "lcgen"); 555 } 556 if(n == Z || n->type == T) 557 return; 558 if(nn == Z) { 559 nn = &nod; 560 regalloc(&nod, n, Z); 561 } 562 switch(n->op) { 563 default: 564 if(n->addable < INDEXED) { 565 diag(n, "unknown op in lcgen: %O", n->op); 566 break; 567 } 568 nod = *n; 569 nod.op = OADDR; 570 nod.left = n; 571 nod.right = Z; 572 nod.type = types[TIND]; 573 gopcode(OAS, &nod, Z, nn); 574 break; 575 576 case OCOMMA: 577 cgen(n->left, n->left); 578 lcgen(n->right, nn); 579 break; 580 581 case OIND: 582 cgen(n->left, nn); 583 break; 584 585 case OCOND: 586 bcgen(n->left, 1); 587 p1 = p; 588 lcgen(n->right->left, nn); 589 gbranch(OGOTO); 590 patch(p1, pc); 591 p1 = p; 592 lcgen(n->right->right, nn); 593 patch(p1, pc); 594 break; 595 } 596 } 597 598 void 599 bcgen(Node *n, int true) 600 { 601 602 if(n->type == T) 603 gbranch(OGOTO); 604 else 605 boolgen(n, true, Z); 606 } 607 608 void 609 boolgen(Node *n, int true, Node *nn) 610 { 611 int o; 612 Prog *p1, *p2; 613 Node *l, *r, nod, nod1; 614 long curs; 615 616 if(debug['g']) { 617 prtree(nn, "boolgen lhs"); 618 prtree(n, "boolgen"); 619 } 620 curs = cursafe; 621 l = n->left; 622 r = n->right; 623 switch(n->op) { 624 625 default: 626 regalloc(&nod, n, nn); 627 cgen(n, &nod); 628 o = ONE; 629 if(true) 630 o = comrel[relindex(o)]; 631 if(typefd[n->type->etype]) { 632 nodreg(&nod1, n, FREGZERO); 633 gopcode(o, &nod, &nod1, Z); 634 } else 635 gopcode(o, nodconst(0), &nod, Z); 636 regfree(&nod); 637 goto com; 638 639 case OCONST: 640 o = vconst(n); 641 if(!true) 642 o = !o; 643 gbranch(OGOTO); 644 if(o) { 645 p1 = p; 646 gbranch(OGOTO); 647 patch(p1, pc); 648 } 649 goto com; 650 651 case OCOMMA: 652 cgen(l, Z); 653 boolgen(r, true, nn); 654 break; 655 656 case ONOT: 657 boolgen(l, !true, nn); 658 break; 659 660 case OCOND: 661 bcgen(l, 1); 662 p1 = p; 663 bcgen(r->left, true); 664 p2 = p; 665 gbranch(OGOTO); 666 patch(p1, pc); 667 p1 = p; 668 bcgen(r->right, !true); 669 patch(p2, pc); 670 p2 = p; 671 gbranch(OGOTO); 672 patch(p1, pc); 673 patch(p2, pc); 674 goto com; 675 676 case OANDAND: 677 if(!true) 678 goto caseor; 679 680 caseand: 681 bcgen(l, true); 682 p1 = p; 683 bcgen(r, !true); 684 p2 = p; 685 patch(p1, pc); 686 gbranch(OGOTO); 687 patch(p2, pc); 688 goto com; 689 690 case OOROR: 691 if(!true) 692 goto caseand; 693 694 caseor: 695 bcgen(l, !true); 696 p1 = p; 697 bcgen(r, !true); 698 p2 = p; 699 gbranch(OGOTO); 700 patch(p1, pc); 701 patch(p2, pc); 702 goto com; 703 704 case OEQ: 705 case ONE: 706 case OLE: 707 case OLT: 708 case OGE: 709 case OGT: 710 case OHI: 711 case OHS: 712 case OLO: 713 case OLS: 714 o = n->op; 715 if(true) 716 o = comrel[relindex(o)]; 717 if(l->complex >= FNX && r->complex >= FNX) { 718 regret(&nod, r); 719 cgen(r, &nod); 720 regsalloc(&nod1, r); 721 gopcode(OAS, &nod, Z, &nod1); 722 regfree(&nod); 723 nod = *n; 724 nod.right = &nod1; 725 boolgen(&nod, true, nn); 726 break; 727 } 728 if(sconst(l)) { 729 regalloc(&nod, r, nn); 730 cgen(r, &nod); 731 gopcode(o, l, &nod, Z); 732 regfree(&nod); 733 goto com; 734 } 735 if(sconst(r)) { 736 regalloc(&nod, l, nn); 737 cgen(l, &nod); 738 o = invrel[relindex(o)]; 739 gopcode(o, r, &nod, Z); 740 regfree(&nod); 741 goto com; 742 } 743 if(l->complex >= r->complex) { 744 regalloc(&nod1, l, nn); 745 cgen(l, &nod1); 746 regalloc(&nod, r, Z); 747 cgen(r, &nod); 748 } else { 749 regalloc(&nod, r, nn); 750 cgen(r, &nod); 751 regalloc(&nod1, l, Z); 752 cgen(l, &nod1); 753 } 754 gopcode(o, &nod1, &nod, Z); 755 regfree(&nod); 756 regfree(&nod1); 757 758 com: 759 if(nn != Z) { 760 p1 = p; 761 gopcode(OAS, nodconst(1L), Z, nn); 762 gbranch(OGOTO); 763 p2 = p; 764 patch(p1, pc); 765 gopcode(OAS, nodconst(0L), Z, nn); 766 patch(p2, pc); 767 } 768 break; 769 } 770 cursafe = curs; 771 } 772 773 void 774 sugen(Node *n, Node *nn, long w) 775 { 776 Prog *p1; 777 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 778 Type *t; 779 long pc1; 780 int i, m, c; 781 782 if(n == Z || n->type == T) 783 return; 784 if(debug['g']) { 785 prtree(nn, "sugen lhs"); 786 prtree(n, "sugen"); 787 } 788 if(nn == nodrat) 789 if(w > nrathole) 790 nrathole = w; 791 switch(n->op) { 792 case OIND: 793 if(nn == Z) { 794 nullwarn(n->left, Z); 795 break; 796 } 797 798 default: 799 goto copy; 800 801 case OCONST: 802 if(n->type && typev[n->type->etype]) { 803 if(nn == Z) { 804 nullwarn(n->left, Z); 805 break; 806 } 807 808 t = nn->type; 809 nn->type = types[TLONG]; 810 reglcgen(&nod1, nn, Z); 811 nn->type = t; 812 813 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 814 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 815 else 816 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 817 nod1.xoffset += SZ_LONG; 818 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 819 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 820 else 821 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 822 823 regfree(&nod1); 824 break; 825 } 826 goto copy; 827 828 case ODOT: 829 l = n->left; 830 sugen(l, nodrat, l->type->width); 831 if(nn != Z) { 832 warn(n, "non-interruptable temporary"); 833 nod1 = *nodrat; 834 r = n->right; 835 if(!r || r->op != OCONST) { 836 diag(n, "DOT and no offset"); 837 break; 838 } 839 nod1.xoffset += (long)r->vconst; 840 nod1.type = n->type; 841 sugen(&nod1, nn, w); 842 } 843 break; 844 845 case OSTRUCT: 846 /* 847 * rewrite so lhs has no fn call 848 */ 849 if(nn != Z && nn->complex >= FNX) { 850 nod1 = *n; 851 nod1.type = typ(TIND, n->type); 852 regret(&nod2, &nod1); 853 lcgen(nn, &nod2); 854 regsalloc(&nod0, &nod1); 855 gopcode(OAS, &nod2, Z, &nod0); 856 regfree(&nod2); 857 858 nod1 = *n; 859 nod1.op = OIND; 860 nod1.left = &nod0; 861 nod1.right = Z; 862 nod1.complex = 1; 863 864 sugen(n, &nod1, w); 865 return; 866 } 867 868 r = n->left; 869 for(t = n->type->link; t != T; t = t->down) { 870 l = r; 871 if(r->op == OLIST) { 872 l = r->left; 873 r = r->right; 874 } 875 if(nn == Z) { 876 cgen(l, nn); 877 continue; 878 } 879 /* 880 * hand craft *(&nn + o) = l 881 */ 882 nod0 = znode; 883 nod0.op = OAS; 884 nod0.type = t; 885 nod0.left = &nod1; 886 nod0.right = l; 887 888 nod1 = znode; 889 nod1.op = OIND; 890 nod1.type = t; 891 nod1.left = &nod2; 892 893 nod2 = znode; 894 nod2.op = OADD; 895 nod2.type = typ(TIND, t); 896 nod2.left = &nod3; 897 nod2.right = &nod4; 898 899 nod3 = znode; 900 nod3.op = OADDR; 901 nod3.type = nod2.type; 902 nod3.left = nn; 903 904 nod4 = znode; 905 nod4.op = OCONST; 906 nod4.type = nod2.type; 907 nod4.vconst = t->offset; 908 909 ccom(&nod0); 910 acom(&nod0); 911 xcom(&nod0); 912 nod0.addable = 0; 913 914 /* prtree(&nod0, "hand craft"); /* */ 915 cgen(&nod0, Z); 916 } 917 break; 918 919 case OAS: 920 if(nn == Z) { 921 if(n->addable < INDEXED) 922 sugen(n->right, n->left, w); 923 break; 924 } 925 sugen(n->right, nodrat, w); 926 warn(n, "non-interruptable temporary"); 927 sugen(nodrat, n->left, w); 928 sugen(nodrat, nn, w); 929 break; 930 931 case OFUNC: 932 if(nn == Z) { 933 sugen(n, nodrat, w); 934 break; 935 } 936 if(nn->op != OIND) { 937 nn = new1(OADDR, nn, Z); 938 nn->type = types[TIND]; 939 nn->addable = 0; 940 } else 941 nn = nn->left; 942 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 943 n->type = types[TVOID]; 944 n->left->type = types[TVOID]; 945 cgen(n, Z); 946 break; 947 948 case OCOND: 949 bcgen(n->left, 1); 950 p1 = p; 951 sugen(n->right->left, nn, w); 952 gbranch(OGOTO); 953 patch(p1, pc); 954 p1 = p; 955 sugen(n->right->right, nn, w); 956 patch(p1, pc); 957 break; 958 959 case OCOMMA: 960 cgen(n->left, Z); 961 sugen(n->right, nn, w); 962 break; 963 } 964 return; 965 966 copy: 967 if(nn == Z) 968 return; 969 if(n->complex >= FNX && nn->complex >= FNX) { 970 t = nn->type; 971 nn->type = types[TLONG]; 972 regialloc(&nod1, nn, Z); 973 lcgen(nn, &nod1); 974 regsalloc(&nod2, nn); 975 nn->type = t; 976 977 gopcode(OAS, &nod1, Z, &nod2); 978 regfree(&nod1); 979 980 nod2.type = typ(TIND, t); 981 982 nod1 = nod2; 983 nod1.op = OIND; 984 nod1.left = &nod2; 985 nod1.right = Z; 986 nod1.complex = 1; 987 nod1.type = t; 988 989 sugen(n, &nod1, w); 990 return; 991 } 992 993 if(n->complex > nn->complex) { 994 t = n->type; 995 n->type = types[TLONG]; 996 reglcgen(&nod1, n, Z); 997 n->type = t; 998 999 t = nn->type; 1000 nn->type = types[TLONG]; 1001 reglcgen(&nod2, nn, Z); 1002 nn->type = t; 1003 } else { 1004 t = nn->type; 1005 nn->type = types[TLONG]; 1006 reglcgen(&nod2, nn, Z); 1007 nn->type = t; 1008 1009 t = n->type; 1010 n->type = types[TLONG]; 1011 reglcgen(&nod1, n, Z); 1012 n->type = t; 1013 } 1014 1015 w /= SZ_LONG; 1016 if(w <= 5) { 1017 layout(&nod1, &nod2, w, 0, Z); 1018 goto out; 1019 } 1020 1021 /* 1022 * minimize space for unrolling loop 1023 * 3,4,5 times. (6 or more is never minimum) 1024 * if small structure, try 2 also. 1025 */ 1026 c = 0; /* set */ 1027 m = 100; 1028 i = 3; 1029 if(w <= 15) 1030 i = 2; 1031 for(; i<=5; i++) 1032 if(i + w%i <= m) { 1033 c = i; 1034 m = c + w%c; 1035 } 1036 1037 regalloc(&nod3, ®node, Z); 1038 layout(&nod1, &nod2, w%c, w/c, &nod3); 1039 1040 pc1 = pc; 1041 layout(&nod1, &nod2, c, 0, Z); 1042 1043 gopcode(OSUB, nodconst(1L), Z, &nod3); 1044 nod1.op = OREGISTER; 1045 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1); 1046 nod2.op = OREGISTER; 1047 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2); 1048 1049 gopcode(OLT, nodconst(0L), &nod3, Z); 1050 patch(p, pc1); 1051 1052 regfree(&nod3); 1053 out: 1054 regfree(&nod1); 1055 regfree(&nod2); 1056 } 1057 1058 void 1059 layout(Node *f, Node *t, int c, int cv, Node *cn) 1060 { 1061 Node t1, t2; 1062 1063 while(c > 3) { 1064 layout(f, t, 2, 0, Z); 1065 c -= 2; 1066 } 1067 1068 regalloc(&t1, ®node, Z); 1069 regalloc(&t2, ®node, Z); 1070 if(c > 0) { 1071 gopcode(OAS, f, Z, &t1); 1072 f->xoffset += SZ_LONG; 1073 } 1074 if(cn != Z) 1075 gopcode(OAS, nodconst(cv), Z, cn); 1076 if(c > 1) { 1077 gopcode(OAS, f, Z, &t2); 1078 f->xoffset += SZ_LONG; 1079 } 1080 if(c > 0) { 1081 gopcode(OAS, &t1, Z, t); 1082 t->xoffset += SZ_LONG; 1083 } 1084 if(c > 2) { 1085 gopcode(OAS, f, Z, &t1); 1086 f->xoffset += SZ_LONG; 1087 } 1088 if(c > 1) { 1089 gopcode(OAS, &t2, Z, t); 1090 t->xoffset += SZ_LONG; 1091 } 1092 if(c > 2) { 1093 gopcode(OAS, &t1, Z, t); 1094 t->xoffset += SZ_LONG; 1095 } 1096 regfree(&t1); 1097 regfree(&t2); 1098 } 1099