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) { 77 if(nn != Z || r->addable < INDEXED) { 78 regalloc(&nod, r, nn); 79 cgen(r, &nod); 80 gmove(&nod, l); 81 regfree(&nod); 82 } else 83 gmove(r, l); 84 break; 85 } 86 if(l->complex >= r->complex) { 87 reglcgen(&nod1, l, Z); 88 if(r->addable >= INDEXED) { 89 gmove(r, &nod1); 90 if(nn != Z) 91 gmove(r, nn); 92 regfree(&nod1); 93 break; 94 } 95 regalloc(&nod, r, nn); 96 cgen(r, &nod); 97 } else { 98 regalloc(&nod, r, nn); 99 cgen(r, &nod); 100 reglcgen(&nod1, l, Z); 101 } 102 gmove(&nod, &nod1); 103 regfree(&nod); 104 regfree(&nod1); 105 break; 106 107 bitas: 108 n = l->left; 109 regalloc(&nod, r, nn); 110 if(l->complex >= r->complex) { 111 reglcgen(&nod1, n, Z); 112 cgen(r, &nod); 113 } else { 114 cgen(r, &nod); 115 reglcgen(&nod1, n, Z); 116 } 117 regalloc(&nod2, n, Z); 118 gopcode(OAS, &nod1, Z, &nod2); 119 bitstore(l, &nod, &nod1, &nod2, nn); 120 break; 121 122 case OBIT: 123 if(nn == Z) { 124 nullwarn(l, Z); 125 break; 126 } 127 bitload(n, &nod, Z, Z, nn); 128 gopcode(OAS, &nod, Z, nn); 129 regfree(&nod); 130 break; 131 132 case OXOR: 133 if(nn != Z) 134 if(r->op == OCONST && r->vconst == -1){ 135 cgen(l, nn); 136 gopcode(OCOM, nn, Z, nn); 137 break; 138 } 139 140 case OADD: 141 case OSUB: 142 case OAND: 143 case OOR: 144 case OLSHR: 145 case OASHL: 146 case OASHR: 147 /* 148 * immediate operands 149 */ 150 if(nn != Z) 151 if(r->op == OCONST) 152 if(!typefd[n->type->etype]) { 153 cgen(l, nn); 154 if(r->vconst == 0) 155 if(o != OAND) 156 break; 157 if(nn != Z) 158 gopcode(o, r, Z, nn); 159 break; 160 } 161 162 case OMUL: 163 case OLMUL: 164 case OLDIV: 165 case OLMOD: 166 case ODIV: 167 case OMOD: 168 if(nn == Z) { 169 nullwarn(l, r); 170 break; 171 } 172 if(o == OMUL || o == OLMUL) { 173 if(mulcon(n, nn)) 174 break; 175 if(debug['M']) 176 print("%L multiply\n", n->lineno); 177 } 178 if(l->complex >= r->complex) { 179 regalloc(&nod, l, nn); 180 cgen(l, &nod); 181 regalloc(&nod1, r, Z); 182 cgen(r, &nod1); 183 gopcode(o, &nod1, Z, &nod); 184 } else { 185 regalloc(&nod, r, nn); 186 cgen(r, &nod); 187 regalloc(&nod1, l, Z); 188 cgen(l, &nod1); 189 gopcode(o, &nod, &nod1, &nod); 190 } 191 gopcode(OAS, &nod, Z, nn); 192 regfree(&nod); 193 regfree(&nod1); 194 break; 195 196 case OASLSHR: 197 case OASASHL: 198 case OASASHR: 199 case OASAND: 200 case OASADD: 201 case OASSUB: 202 case OASXOR: 203 case OASOR: 204 if(l->op == OBIT) 205 goto asbitop; 206 if(r->op == OCONST) 207 if(!typefd[r->type->etype]) 208 if(!typefd[n->type->etype]) { 209 if(l->addable < INDEXED) 210 reglcgen(&nod2, l, Z); 211 else 212 nod2 = *l; 213 regalloc(&nod, r, nn); 214 gopcode(OAS, &nod2, Z, &nod); 215 gopcode(o, r, Z, &nod); 216 gopcode(OAS, &nod, Z, &nod2); 217 218 regfree(&nod); 219 if(l->addable < INDEXED) 220 regfree(&nod2); 221 break; 222 } 223 224 case OASLMUL: 225 case OASLDIV: 226 case OASLMOD: 227 case OASMUL: 228 case OASDIV: 229 case OASMOD: 230 if(l->op == OBIT) 231 goto asbitop; 232 if(l->complex >= r->complex) { 233 if(l->addable < INDEXED) 234 reglcgen(&nod2, l, Z); 235 else 236 nod2 = *l; 237 regalloc(&nod, n, nn); 238 cgen(r, &nod); 239 } else { 240 regalloc(&nod, n, nn); 241 cgen(r, &nod); 242 if(l->addable < INDEXED) 243 reglcgen(&nod2, l, Z); 244 else 245 nod2 = *l; 246 } 247 regalloc(&nod1, n, Z); 248 gopcode(OAS, &nod2, Z, &nod1); 249 gopcode(o, &nod, &nod1, &nod); 250 gopcode(OAS, &nod, Z, &nod2); 251 regfree(&nod); 252 regfree(&nod1); 253 if(l->addable < INDEXED) 254 regfree(&nod2); 255 break; 256 257 asbitop: 258 regalloc(&nod4, n, nn); 259 regalloc(&nod3, r, Z); 260 if(l->complex >= r->complex) { 261 bitload(l, &nod, &nod1, &nod2, &nod4); 262 cgen(r, &nod3); 263 } else { 264 cgen(r, &nod3); 265 bitload(l, &nod, &nod1, &nod2, &nod4); 266 } 267 gmove(&nod, &nod4); 268 gopcode(n->op, &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 cgen(l, nn); 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) && nocast(n->type, nn->type)) { 389 /* both null, gen l->nn */ 390 cgen(l, nn); 391 break; 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 if(n->op == OCONST) { 627 o = vconst(n); 628 if(!true) 629 o = !o; 630 gbranch(OGOTO); 631 if(o) { 632 p1 = p; 633 gbranch(OGOTO); 634 patch(p1, pc); 635 } 636 goto com; 637 } 638 regalloc(&nod, n, nn); 639 cgen(n, &nod); 640 o = ONE; 641 if(true) 642 o = comrel[relindex(o)]; 643 if(typefd[n->type->etype]) { 644 nodreg(&nod1, n, NREG+FREGZERO); 645 gopcode(o, &nod, Z, &nod1); 646 } else 647 gopcode(o, &nod, Z, nodconst(0)); 648 regfree(&nod); 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(r)) { 729 regalloc(&nod, l, nn); 730 cgen(l, &nod); 731 gopcode(o, &nod, Z, r); 732 regfree(&nod); 733 goto com; 734 } 735 if(l->complex >= r->complex) { 736 regalloc(&nod1, l, nn); 737 cgen(l, &nod1); 738 regalloc(&nod, r, Z); 739 cgen(r, &nod); 740 } else { 741 regalloc(&nod, r, nn); 742 cgen(r, &nod); 743 regalloc(&nod1, l, Z); 744 cgen(l, &nod1); 745 } 746 gopcode(o, &nod1, Z, &nod); 747 regfree(&nod); 748 regfree(&nod1); 749 750 com: 751 if(nn != Z) { 752 p1 = p; 753 gopcode(OAS, nodconst(1L), Z, nn); 754 gbranch(OGOTO); 755 p2 = p; 756 patch(p1, pc); 757 gopcode(OAS, nodconst(0L), Z, nn); 758 patch(p2, pc); 759 } 760 break; 761 } 762 cursafe = curs; 763 } 764 765 void 766 sugen(Node *n, Node *nn, long w) 767 { 768 Prog *p1; 769 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 770 Type *t; 771 long pc1; 772 int i, m, c; 773 774 if(n == Z || n->type == T) 775 return; 776 if(debug['g']) { 777 prtree(nn, "sugen lhs"); 778 prtree(n, "sugen"); 779 } 780 if(nn == nodrat) 781 if(w > nrathole) 782 nrathole = w; 783 switch(n->op) { 784 case OIND: 785 if(nn == Z) { 786 nullwarn(n->left, Z); 787 break; 788 } 789 790 default: 791 goto copy; 792 793 case OCONST: 794 if(n->type && typev[n->type->etype]) { 795 if(nn == Z) { 796 nullwarn(n->left, Z); 797 break; 798 } 799 800 t = nn->type; 801 nn->type = types[TLONG]; 802 reglcgen(&nod1, nn, Z); 803 nn->type = t; 804 805 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 806 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 807 else 808 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 809 nod1.xoffset += SZ_LONG; 810 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 811 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 812 else 813 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 814 815 regfree(&nod1); 816 break; 817 } 818 goto copy; 819 820 case ODOT: 821 l = n->left; 822 sugen(l, nodrat, l->type->width); 823 if(nn != Z) { 824 warn(n, "non-interruptable temporary"); 825 nod1 = *nodrat; 826 r = n->right; 827 if(!r || r->op != OCONST) { 828 diag(n, "DOT and no offset"); 829 break; 830 } 831 nod1.xoffset += (long)r->vconst; 832 nod1.type = n->type; 833 sugen(&nod1, nn, w); 834 } 835 break; 836 837 case OSTRUCT: 838 /* 839 * rewrite so lhs has no side effects 840 */ 841 if(nn != Z && side(nn)) { 842 nod1 = *n; 843 nod1.type = typ(TIND, n->type); 844 regalloc(&nod2, &nod1, Z); 845 lcgen(nn, &nod2); 846 regsalloc(&nod0, &nod1); 847 gopcode(OAS, &nod2, Z, &nod0); 848 regfree(&nod2); 849 850 nod1 = *n; 851 nod1.op = OIND; 852 nod1.left = &nod0; 853 nod1.right = Z; 854 nod1.complex = 1; 855 856 sugen(n, &nod1, w); 857 return; 858 } 859 860 r = n->left; 861 for(t = n->type->link; t != T; t = t->down) { 862 l = r; 863 if(r->op == OLIST) { 864 l = r->left; 865 r = r->right; 866 } 867 if(nn == Z) { 868 cgen(l, nn); 869 continue; 870 } 871 /* 872 * hand craft *(&nn + o) = l 873 */ 874 nod0 = znode; 875 nod0.op = OAS; 876 nod0.type = t; 877 nod0.left = &nod1; 878 nod0.right = l; 879 880 nod1 = znode; 881 nod1.op = OIND; 882 nod1.type = t; 883 nod1.left = &nod2; 884 885 nod2 = znode; 886 nod2.op = OADD; 887 nod2.type = typ(TIND, t); 888 nod2.left = &nod3; 889 nod2.right = &nod4; 890 891 nod3 = znode; 892 nod3.op = OADDR; 893 nod3.type = nod2.type; 894 nod3.left = nn; 895 896 nod4 = znode; 897 nod4.op = OCONST; 898 nod4.type = nod2.type; 899 nod4.vconst = t->offset; 900 901 ccom(&nod0); 902 acom(&nod0); 903 xcom(&nod0); 904 nod0.addable = 0; 905 906 /* prtree(&nod0, "hand craft"); /* */ 907 cgen(&nod0, Z); 908 } 909 break; 910 911 case OAS: 912 if(nn == Z) { 913 if(n->addable < INDEXED) 914 sugen(n->right, n->left, w); 915 break; 916 } 917 /* BOTCH -- functions can clobber rathole */ 918 sugen(n->right, nodrat, w); 919 warn(n, "non-interruptable temporary"); 920 sugen(nodrat, n->left, w); 921 sugen(nodrat, nn, w); 922 break; 923 924 case OFUNC: 925 if(nn == Z) { 926 sugen(n, nodrat, w); 927 break; 928 } 929 if(nn->op != OIND) { 930 nn = new1(OADDR, nn, Z); 931 nn->type = types[TIND]; 932 nn->addable = 0; 933 } else 934 nn = nn->left; 935 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 936 n->type = types[TVOID]; 937 n->left->type = types[TVOID]; 938 cgen(n, Z); 939 break; 940 941 case OCOND: 942 bcgen(n->left, 1); 943 p1 = p; 944 sugen(n->right->left, nn, w); 945 gbranch(OGOTO); 946 patch(p1, pc); 947 p1 = p; 948 sugen(n->right->right, nn, w); 949 patch(p1, pc); 950 break; 951 952 case OCOMMA: 953 cgen(n->left, Z); 954 sugen(n->right, nn, w); 955 break; 956 } 957 return; 958 959 copy: 960 if(nn == Z) 961 return; 962 if(n->complex >= FNX && nn->complex >= FNX) { 963 t = nn->type; 964 nn->type = types[TLONG]; 965 regialloc(&nod1, nn, Z); 966 lcgen(nn, &nod1); 967 regsalloc(&nod2, nn); 968 nn->type = t; 969 970 gopcode(OAS, &nod1, Z, &nod2); 971 regfree(&nod1); 972 973 nod2.type = typ(TIND, t); 974 975 nod1 = nod2; 976 nod1.op = OIND; 977 nod1.left = &nod2; 978 nod1.right = Z; 979 nod1.complex = 1; 980 nod1.type = t; 981 982 sugen(n, &nod1, w); 983 return; 984 } 985 986 if(n->complex > nn->complex) { 987 t = n->type; 988 n->type = types[TLONG]; 989 reglcgen(&nod1, n, Z); 990 n->type = t; 991 992 t = nn->type; 993 nn->type = types[TLONG]; 994 reglcgen(&nod2, nn, Z); 995 nn->type = t; 996 } else { 997 t = nn->type; 998 nn->type = types[TLONG]; 999 reglcgen(&nod2, nn, Z); 1000 nn->type = t; 1001 1002 t = n->type; 1003 n->type = types[TLONG]; 1004 reglcgen(&nod1, n, Z); 1005 n->type = t; 1006 } 1007 1008 w /= SZ_LONG; 1009 if(w <= 5) { 1010 layout(&nod1, &nod2, w, 0, Z); 1011 goto out; 1012 } 1013 1014 /* 1015 * minimize space for unrolling loop 1016 * 3,4,5 times. (6 or more is never minimum) 1017 * if small structure, try 2 also. 1018 */ 1019 c = 0; /* set */ 1020 m = 100; 1021 i = 3; 1022 if(w <= 15) 1023 i = 2; 1024 for(; i<=5; i++) 1025 if(i + w%i <= m) { 1026 c = i; 1027 m = c + w%c; 1028 } 1029 1030 regalloc(&nod3, ®node, Z); 1031 layout(&nod1, &nod2, w%c, w/c, &nod3); 1032 1033 pc1 = pc; 1034 layout(&nod1, &nod2, c, 0, Z); 1035 1036 gopcode(OSUB, nodconst(1L), Z, &nod3); 1037 nod1.op = OREGISTER; 1038 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1); 1039 nod2.op = OREGISTER; 1040 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2); 1041 1042 gopcode(OGT, &nod3, Z, nodconst(0)); 1043 patch(p, pc1); 1044 1045 regfree(&nod3); 1046 out: 1047 regfree(&nod1); 1048 regfree(&nod2); 1049 } 1050 1051 void 1052 layout(Node *f, Node *t, int c, int cv, Node *cn) 1053 { 1054 Node t1, t2; 1055 1056 while(c > 3) { 1057 layout(f, t, 2, 0, Z); 1058 c -= 2; 1059 } 1060 1061 regalloc(&t1, ®node, Z); 1062 regalloc(&t2, ®node, Z); 1063 if(c > 0) { 1064 gopcode(OAS, f, Z, &t1); 1065 f->xoffset += SZ_LONG; 1066 } 1067 if(cn != Z) 1068 gopcode(OAS, nodconst(cv), Z, cn); 1069 if(c > 1) { 1070 gopcode(OAS, f, Z, &t2); 1071 f->xoffset += SZ_LONG; 1072 } 1073 if(c > 0) { 1074 gopcode(OAS, &t1, Z, t); 1075 t->xoffset += SZ_LONG; 1076 } 1077 if(c > 2) { 1078 gopcode(OAS, f, Z, &t1); 1079 f->xoffset += SZ_LONG; 1080 } 1081 if(c > 1) { 1082 gopcode(OAS, &t2, Z, t); 1083 t->xoffset += SZ_LONG; 1084 } 1085 if(c > 2) { 1086 gopcode(OAS, &t1, Z, t); 1087 t->xoffset += SZ_LONG; 1088 } 1089 regfree(&t1); 1090 regfree(&t2); 1091 } 1092