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