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