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