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 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 OMUL: 161 case OLMUL: 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 if(debug['M']) 174 print("%L multiply\n", n->lineno); 175 } 176 if(l->complex >= r->complex) { 177 regalloc(&nod, l, nn); 178 cgen(l, &nod); 179 regalloc(&nod1, r, Z); 180 cgen(r, &nod1); 181 gopcode(o, &nod1, Z, &nod); 182 } else { 183 regalloc(&nod, r, nn); 184 cgen(r, &nod); 185 regalloc(&nod1, l, Z); 186 cgen(l, &nod1); 187 gopcode(o, &nod, &nod1, &nod); 188 } 189 gopcode(OAS, &nod, Z, nn); 190 regfree(&nod); 191 regfree(&nod1); 192 break; 193 194 case OASLSHR: 195 case OASASHL: 196 case OASASHR: 197 case OASAND: 198 case OASADD: 199 case OASSUB: 200 case OASXOR: 201 case OASOR: 202 if(l->op == OBIT) 203 goto asbitop; 204 if(r->op == OCONST) 205 if(!typefd[n->type->etype]) { 206 if(l->addable < INDEXED) 207 reglcgen(&nod2, l, Z); 208 else 209 nod2 = *l; 210 regalloc(&nod, r, nn); 211 gopcode(OAS, &nod2, Z, &nod); 212 gopcode(o, r, Z, &nod); 213 gopcode(OAS, &nod, Z, &nod2); 214 215 regfree(&nod); 216 if(l->addable < INDEXED) 217 regfree(&nod2); 218 break; 219 } 220 221 case OASLMUL: 222 case OASLDIV: 223 case OASLMOD: 224 case OASMUL: 225 case OASDIV: 226 case OASMOD: 227 if(l->op == OBIT) 228 goto asbitop; 229 if(l->complex >= r->complex) { 230 if(l->addable < INDEXED) 231 reglcgen(&nod2, l, Z); 232 else 233 nod2 = *l; 234 regalloc(&nod, n, nn); 235 cgen(r, &nod); 236 } else { 237 regalloc(&nod, n, nn); 238 cgen(r, &nod); 239 if(l->addable < INDEXED) 240 reglcgen(&nod2, l, Z); 241 else 242 nod2 = *l; 243 } 244 regalloc(&nod1, n, Z); 245 gopcode(OAS, &nod2, Z, &nod1); 246 gopcode(o, &nod, &nod1, &nod); 247 gopcode(OAS, &nod, Z, &nod2); 248 regfree(&nod); 249 regfree(&nod1); 250 if(l->addable < INDEXED) 251 regfree(&nod2); 252 break; 253 254 asbitop: 255 regalloc(&nod4, n, nn); 256 regalloc(&nod3, r, Z); 257 if(l->complex >= r->complex) { 258 bitload(l, &nod, &nod1, &nod2, &nod4); 259 cgen(r, &nod3); 260 } else { 261 cgen(r, &nod3); 262 bitload(l, &nod, &nod1, &nod2, &nod4); 263 } 264 gmove(&nod, &nod4); 265 gopcode(n->op, &nod3, Z, &nod4); 266 regfree(&nod3); 267 gmove(&nod4, &nod); 268 regfree(&nod4); 269 bitstore(l, &nod, &nod1, &nod2, nn); 270 break; 271 272 case OADDR: 273 if(nn == Z) { 274 nullwarn(l, Z); 275 break; 276 } 277 lcgen(l, nn); 278 break; 279 280 case OFUNC: 281 if(l->complex >= FNX) { 282 if(l->op != OIND) 283 diag(n, "bad function call"); 284 285 regret(&nod, l->left); 286 cgen(l->left, &nod); 287 regsalloc(&nod1, l->left); 288 gopcode(OAS, &nod, Z, &nod1); 289 regfree(&nod); 290 291 nod = *n; 292 nod.left = &nod2; 293 nod2 = *l; 294 nod2.left = &nod1; 295 nod2.complex = 1; 296 cgen(&nod, nn); 297 298 return; 299 } 300 o = reg[REGARG]; 301 gargs(r, &nod, &nod1); 302 if(l->addable < INDEXED) { 303 reglcgen(&nod, l, Z); 304 gopcode(OFUNC, Z, Z, &nod); 305 regfree(&nod); 306 } else 307 gopcode(OFUNC, Z, Z, l); 308 if(REGARG) 309 if(o != reg[REGARG]) 310 reg[REGARG]--; 311 if(nn != Z) { 312 regret(&nod, n); 313 gopcode(OAS, &nod, Z, nn); 314 regfree(&nod); 315 } 316 break; 317 318 case OIND: 319 if(nn == Z) { 320 cgen(l, nn); 321 break; 322 } 323 regialloc(&nod, n, nn); 324 r = l; 325 while(r->op == OADD) 326 r = r->right; 327 if(sconst(r)) { 328 v = r->vconst; 329 r->vconst = 0; 330 cgen(l, &nod); 331 nod.xoffset += v; 332 r->vconst = v; 333 } else 334 cgen(l, &nod); 335 regind(&nod, n); 336 gopcode(OAS, &nod, Z, nn); 337 regfree(&nod); 338 break; 339 340 case OEQ: 341 case ONE: 342 case OLE: 343 case OLT: 344 case OGE: 345 case OGT: 346 case OLO: 347 case OLS: 348 case OHI: 349 case OHS: 350 if(nn == Z) { 351 nullwarn(l, r); 352 break; 353 } 354 boolgen(n, 1, nn); 355 break; 356 357 case OANDAND: 358 case OOROR: 359 boolgen(n, 1, nn); 360 if(nn == Z) 361 patch(p, pc); 362 break; 363 364 case ONOT: 365 if(nn == Z) { 366 nullwarn(l, Z); 367 break; 368 } 369 boolgen(n, 1, nn); 370 break; 371 372 case OCOMMA: 373 cgen(l, Z); 374 cgen(r, nn); 375 break; 376 377 case OCAST: 378 if(nn == Z) { 379 nullwarn(l, Z); 380 break; 381 } 382 /* 383 * convert from types l->n->nn 384 */ 385 if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { 386 /* both null, gen l->nn */ 387 cgen(l, nn); 388 break; 389 } 390 regalloc(&nod, l, nn); 391 cgen(l, &nod); 392 regalloc(&nod1, n, &nod); 393 gopcode(OAS, &nod, Z, &nod1); 394 gopcode(OAS, &nod1, Z, nn); 395 regfree(&nod1); 396 regfree(&nod); 397 break; 398 399 case ODOT: 400 sugen(l, nodrat, l->type->width); 401 if(nn != Z) { 402 warn(n, "non-interruptable temporary"); 403 nod = *nodrat; 404 if(!r || r->op != OCONST) { 405 diag(n, "DOT and no offset"); 406 break; 407 } 408 nod.xoffset += (long)r->vconst; 409 nod.type = n->type; 410 cgen(&nod, nn); 411 } 412 break; 413 414 case OCOND: 415 bcgen(l, 1); 416 p1 = p; 417 cgen(r->left, nn); 418 gbranch(OGOTO); 419 patch(p1, pc); 420 p1 = p; 421 cgen(r->right, nn); 422 patch(p1, pc); 423 break; 424 425 case OPOSTINC: 426 case OPOSTDEC: 427 v = 1; 428 if(l->type->etype == TIND) 429 v = l->type->link->width; 430 if(o == OPOSTDEC) 431 v = -v; 432 if(l->op == OBIT) 433 goto bitinc; 434 if(nn == Z) 435 goto pre; 436 437 if(l->addable < INDEXED) 438 reglcgen(&nod2, l, Z); 439 else 440 nod2 = *l; 441 442 regalloc(&nod, l, nn); 443 gopcode(OAS, &nod2, Z, &nod); 444 regalloc(&nod1, l, Z); 445 if(typefd[l->type->etype]) { 446 regalloc(&nod3, l, Z); 447 if(v < 0) { 448 gopcode(OAS, nodfconst(-v), Z, &nod3); 449 gopcode(OSUB, &nod3, &nod, &nod1); 450 } else { 451 gopcode(OAS, nodfconst(v), Z, &nod3); 452 gopcode(OADD, &nod3, &nod, &nod1); 453 } 454 regfree(&nod3); 455 } else 456 gopcode(OADD, nodconst(v), &nod, &nod1); 457 gopcode(OAS, &nod1, Z, &nod2); 458 459 regfree(&nod); 460 regfree(&nod1); 461 if(l->addable < INDEXED) 462 regfree(&nod2); 463 break; 464 465 case OPREINC: 466 case OPREDEC: 467 v = 1; 468 if(l->type->etype == TIND) 469 v = l->type->link->width; 470 if(o == OPREDEC) 471 v = -v; 472 if(l->op == OBIT) 473 goto bitinc; 474 475 pre: 476 if(l->addable < INDEXED) 477 reglcgen(&nod2, l, Z); 478 else 479 nod2 = *l; 480 481 regalloc(&nod, l, nn); 482 gopcode(OAS, &nod2, Z, &nod); 483 if(typefd[l->type->etype]) { 484 regalloc(&nod3, l, Z); 485 if(v < 0) { 486 gopcode(OAS, nodfconst(-v), Z, &nod3); 487 gopcode(OSUB, &nod3, Z, &nod); 488 } else { 489 gopcode(OAS, nodfconst(v), Z, &nod3); 490 gopcode(OADD, &nod3, Z, &nod); 491 } 492 regfree(&nod3); 493 } else 494 gopcode(OADD, nodconst(v), Z, &nod); 495 gopcode(OAS, &nod, Z, &nod2); 496 if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ 497 gins(ANOP, l, Z); 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 fn call 839 */ 840 if(nn != Z && nn->complex >= FNX) { 841 nod1 = *n; 842 nod1.type = typ(TIND, n->type); 843 regret(&nod2, &nod1); 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 cgen(&nod0, Z); 906 } 907 break; 908 909 case OAS: 910 if(nn == Z) { 911 if(n->addable < INDEXED) 912 sugen(n->right, n->left, w); 913 break; 914 } 915 /* BOTCH -- functions can clobber rathole */ 916 sugen(n->right, nodrat, w); 917 warn(n, "non-interruptable temporary"); 918 sugen(nodrat, n->left, w); 919 sugen(nodrat, nn, w); 920 break; 921 922 case OFUNC: 923 if(nn == Z) { 924 sugen(n, nodrat, w); 925 break; 926 } 927 if(nn->op != OIND) { 928 nn = new1(OADDR, nn, Z); 929 nn->type = types[TIND]; 930 nn->addable = 0; 931 } else 932 nn = nn->left; 933 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 934 n->type = types[TVOID]; 935 n->left->type = types[TVOID]; 936 cgen(n, Z); 937 break; 938 939 case OCOND: 940 bcgen(n->left, 1); 941 p1 = p; 942 sugen(n->right->left, nn, w); 943 gbranch(OGOTO); 944 patch(p1, pc); 945 p1 = p; 946 sugen(n->right->right, nn, w); 947 patch(p1, pc); 948 break; 949 950 case OCOMMA: 951 cgen(n->left, Z); 952 sugen(n->right, nn, w); 953 break; 954 } 955 return; 956 957 copy: 958 if(nn == Z) 959 return; 960 if(n->complex >= FNX && nn->complex >= FNX) { 961 t = nn->type; 962 nn->type = types[TLONG]; 963 regialloc(&nod1, nn, Z); 964 lcgen(nn, &nod1); 965 regsalloc(&nod2, nn); 966 nn->type = t; 967 968 gopcode(OAS, &nod1, Z, &nod2); 969 regfree(&nod1); 970 971 nod2.type = typ(TIND, t); 972 973 nod1 = nod2; 974 nod1.op = OIND; 975 nod1.left = &nod2; 976 nod1.right = Z; 977 nod1.complex = 1; 978 nod1.type = t; 979 980 sugen(n, &nod1, w); 981 return; 982 } 983 984 if(n->complex > nn->complex) { 985 t = n->type; 986 n->type = types[TLONG]; 987 reglcgen(&nod1, n, Z); 988 n->type = t; 989 990 t = nn->type; 991 nn->type = types[TLONG]; 992 reglcgen(&nod2, nn, Z); 993 nn->type = t; 994 } else { 995 t = nn->type; 996 nn->type = types[TLONG]; 997 reglcgen(&nod2, nn, Z); 998 nn->type = t; 999 1000 t = n->type; 1001 n->type = types[TLONG]; 1002 reglcgen(&nod1, n, Z); 1003 n->type = t; 1004 } 1005 1006 w /= SZ_LONG; 1007 if(w <= 5) { 1008 layout(&nod1, &nod2, w, 0, Z); 1009 goto out; 1010 } 1011 1012 /* 1013 * minimize space for unrolling loop 1014 * 3,4,5 times. (6 or more is never minimum) 1015 * if small structure, try 2 also. 1016 */ 1017 c = 0; /* set */ 1018 m = 100; 1019 i = 3; 1020 if(w <= 15) 1021 i = 2; 1022 for(; i<=5; i++) 1023 if(i + w%i <= m) { 1024 c = i; 1025 m = c + w%c; 1026 } 1027 1028 regalloc(&nod3, ®node, Z); 1029 layout(&nod1, &nod2, w%c, w/c, &nod3); 1030 1031 pc1 = pc; 1032 layout(&nod1, &nod2, c, 0, Z); 1033 1034 gopcode(OSUB, nodconst(1L), Z, &nod3); 1035 nod1.op = OREGISTER; 1036 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1); 1037 nod2.op = OREGISTER; 1038 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2); 1039 1040 gopcode(OGT, &nod3, Z, nodconst(0)); 1041 patch(p, pc1); 1042 1043 regfree(&nod3); 1044 out: 1045 regfree(&nod1); 1046 regfree(&nod2); 1047 } 1048 1049 void 1050 layout(Node *f, Node *t, int c, int cv, Node *cn) 1051 { 1052 Node t1, t2; 1053 1054 while(c > 3) { 1055 layout(f, t, 2, 0, Z); 1056 c -= 2; 1057 } 1058 1059 regalloc(&t1, ®node, Z); 1060 regalloc(&t2, ®node, Z); 1061 if(c > 0) { 1062 gopcode(OAS, f, Z, &t1); 1063 f->xoffset += SZ_LONG; 1064 } 1065 if(cn != Z) 1066 gopcode(OAS, nodconst(cv), Z, cn); 1067 if(c > 1) { 1068 gopcode(OAS, f, Z, &t2); 1069 f->xoffset += SZ_LONG; 1070 } 1071 if(c > 0) { 1072 gopcode(OAS, &t1, Z, t); 1073 t->xoffset += SZ_LONG; 1074 } 1075 if(c > 2) { 1076 gopcode(OAS, f, Z, &t1); 1077 f->xoffset += SZ_LONG; 1078 } 1079 if(c > 1) { 1080 gopcode(OAS, &t2, Z, t); 1081 t->xoffset += SZ_LONG; 1082 } 1083 if(c > 2) { 1084 gopcode(OAS, &t1, Z, t); 1085 t->xoffset += SZ_LONG; 1086 } 1087 regfree(&t1); 1088 regfree(&t2); 1089 } 1090