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