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