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