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