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