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