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