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