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 501 regfree(&nod); 502 if(l->addable < INDEXED) 503 regfree(&nod2); 504 break; 505 506 bitinc: 507 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 508 bitload(l, &nod, &nod1, &nod2, Z); 509 gopcode(OAS, &nod, Z, nn); 510 gopcode(OADD, nodconst(v), Z, &nod); 511 bitstore(l, &nod, &nod1, &nod2, Z); 512 break; 513 } 514 bitload(l, &nod, &nod1, &nod2, nn); 515 gopcode(OADD, nodconst(v), Z, &nod); 516 bitstore(l, &nod, &nod1, &nod2, nn); 517 break; 518 } 519 cursafe = curs; 520 } 521 522 void 523 reglcgen(Node *t, Node *n, Node *nn) 524 { 525 Node *r; 526 long v; 527 528 regialloc(t, n, nn); 529 if(n->op == OIND) { 530 r = n->left; 531 while(r->op == OADD) 532 r = r->right; 533 if(sconst(r)) { 534 v = r->vconst; 535 r->vconst = 0; 536 lcgen(n, t); 537 t->xoffset += v; 538 r->vconst = v; 539 regind(t, n); 540 return; 541 } 542 } 543 lcgen(n, t); 544 regind(t, n); 545 } 546 547 void 548 lcgen(Node *n, Node *nn) 549 { 550 Prog *p1; 551 Node nod; 552 553 if(debug['g']) { 554 prtree(nn, "lcgen lhs"); 555 prtree(n, "lcgen"); 556 } 557 if(n == Z || n->type == T) 558 return; 559 if(nn == Z) { 560 nn = &nod; 561 regalloc(&nod, n, Z); 562 } 563 switch(n->op) { 564 default: 565 if(n->addable < INDEXED) { 566 diag(n, "unknown op in lcgen: %O", n->op); 567 break; 568 } 569 nod = *n; 570 nod.op = OADDR; 571 nod.left = n; 572 nod.right = Z; 573 nod.type = types[TIND]; 574 gopcode(OAS, &nod, Z, nn); 575 break; 576 577 case OCOMMA: 578 cgen(n->left, n->left); 579 lcgen(n->right, nn); 580 break; 581 582 case OIND: 583 cgen(n->left, nn); 584 break; 585 586 case OCOND: 587 bcgen(n->left, 1); 588 p1 = p; 589 lcgen(n->right->left, nn); 590 gbranch(OGOTO); 591 patch(p1, pc); 592 p1 = p; 593 lcgen(n->right->right, nn); 594 patch(p1, pc); 595 break; 596 } 597 } 598 599 void 600 bcgen(Node *n, int true) 601 { 602 603 if(n->type == T) 604 gbranch(OGOTO); 605 else 606 boolgen(n, true, Z); 607 } 608 609 void 610 boolgen(Node *n, int true, Node *nn) 611 { 612 int o; 613 Prog *p1, *p2; 614 Node *l, *r, nod, nod1; 615 long curs; 616 617 if(debug['g']) { 618 prtree(nn, "boolgen lhs"); 619 prtree(n, "boolgen"); 620 } 621 curs = cursafe; 622 l = n->left; 623 r = n->right; 624 switch(n->op) { 625 626 default: 627 regalloc(&nod, n, nn); 628 cgen(n, &nod); 629 if(nn == Z || typefd[n->type->etype]) { 630 o = ONE; 631 if(true) 632 o = comrel[relindex(o)]; 633 if(typefd[n->type->etype]) { 634 nodreg(&nod1, n, NREG+FREGZERO); 635 gopcode(o, &nod, &nod1, Z); 636 } else 637 gopcode(o, &nod, Z, Z); 638 regfree(&nod); 639 goto com; 640 } 641 if(true) 642 gopcode(OCOND, &nod, nodconst(0), &nod); 643 else 644 gopcode(OCOND, nodconst(1), &nod, &nod); 645 gopcode(OAS, &nod, Z, nn); 646 regfree(&nod); 647 break; 648 649 case OCONST: 650 o = vconst(n); 651 if(!true) 652 o = !o; 653 gbranch(OGOTO); 654 if(o) { 655 p1 = p; 656 gbranch(OGOTO); 657 patch(p1, pc); 658 } 659 goto com; 660 661 case OCOMMA: 662 cgen(l, Z); 663 boolgen(r, true, nn); 664 break; 665 666 case ONOT: 667 boolgen(l, !true, nn); 668 break; 669 670 case OCOND: 671 bcgen(l, 1); 672 p1 = p; 673 bcgen(r->left, true); 674 p2 = p; 675 gbranch(OGOTO); 676 patch(p1, pc); 677 p1 = p; 678 bcgen(r->right, !true); 679 patch(p2, pc); 680 p2 = p; 681 gbranch(OGOTO); 682 patch(p1, pc); 683 patch(p2, pc); 684 goto com; 685 686 case OANDAND: 687 if(!true) 688 goto caseor; 689 690 caseand: 691 bcgen(l, true); 692 p1 = p; 693 bcgen(r, !true); 694 p2 = p; 695 patch(p1, pc); 696 gbranch(OGOTO); 697 patch(p2, pc); 698 goto com; 699 700 case OOROR: 701 if(!true) 702 goto caseand; 703 704 caseor: 705 bcgen(l, !true); 706 p1 = p; 707 bcgen(r, !true); 708 p2 = p; 709 gbranch(OGOTO); 710 patch(p1, pc); 711 patch(p2, pc); 712 goto com; 713 714 case OEQ: 715 case ONE: 716 case OLE: 717 case OLT: 718 case OGE: 719 case OGT: 720 case OHI: 721 case OHS: 722 case OLO: 723 case OLS: 724 o = n->op; 725 if(true) 726 o = comrel[relindex(o)]; 727 if(l->complex >= FNX && r->complex >= FNX) { 728 regret(&nod, r); 729 cgen(r, &nod); 730 regsalloc(&nod1, r); 731 gopcode(OAS, &nod, Z, &nod1); 732 regfree(&nod); 733 nod = *n; 734 nod.right = &nod1; 735 boolgen(&nod, true, nn); 736 break; 737 } 738 if(nn != Z && !typefd[l->type->etype]) { 739 if(l->complex >= r->complex) { 740 regalloc(&nod1, l, nn); 741 cgen(l, &nod1); 742 regalloc(&nod, r, Z); 743 cgen(r, &nod); 744 } else { 745 regalloc(&nod, r, nn); 746 cgen(r, &nod); 747 regalloc(&nod1, l, Z); 748 cgen(l, &nod1); 749 } 750 switch(o) { 751 case OEQ: 752 gopcode(OSUB, &nod1, &nod, &nod); 753 gopcode(OCOND, &nod, nodconst(0), &nod); 754 break; 755 case ONE: 756 gopcode(OSUB, &nod1, &nod, &nod); 757 gopcode(OCOND, nodconst(1), &nod, &nod); 758 break; 759 case OLE: 760 gopcode(OCOMMA, &nod1, &nod, &nod); 761 break; 762 case OGT: 763 gopcode(OCOMMA, &nod1, &nod, &nod); 764 gopcode(OXOR, nodconst(1), &nod, &nod); 765 break; 766 case OLT: 767 gopcode(OCOMMA, &nod, &nod1, &nod); 768 gopcode(OXOR, nodconst(1), &nod, &nod); 769 break; 770 case OGE: 771 gopcode(OCOMMA, &nod, &nod1, &nod); 772 break; 773 case OLS: 774 gopcode(OCOND, &nod1, &nod, &nod); 775 break; 776 case OHI: 777 gopcode(OCOND, &nod1, &nod, &nod); 778 gopcode(OXOR, nodconst(1), &nod, &nod); 779 break; 780 case OLO: 781 gopcode(OCOND, &nod, &nod1, &nod); 782 gopcode(OXOR, nodconst(1), &nod, &nod); 783 break; 784 case OHS: 785 gopcode(OCOND, &nod, &nod1, &nod); 786 break; 787 } 788 gopcode(OAS, &nod, Z, nn); 789 regfree(&nod); 790 regfree(&nod1); 791 break; 792 } 793 if(sconst(l)) { 794 switch(o) { 795 default: 796 if(l->vconst != 0) 797 break; 798 799 case OGT: 800 case OHI: 801 case OLE: 802 case OLS: 803 regalloc(&nod, r, nn); 804 cgen(r, &nod); 805 gopcode(o, l, &nod, Z); 806 regfree(&nod); 807 goto com; 808 } 809 } 810 if(sconst(r)) { 811 switch(o) { 812 default: 813 if(r->vconst != 0) 814 break; 815 816 case OGE: 817 case OHS: 818 case OLT: 819 case OLO: 820 regalloc(&nod, l, nn); 821 cgen(l, &nod); 822 gopcode(o, &nod, r, Z); 823 regfree(&nod); 824 goto com; 825 } 826 } 827 if(l->complex >= r->complex) { 828 regalloc(&nod1, l, nn); 829 cgen(l, &nod1); 830 regalloc(&nod, r, Z); 831 cgen(r, &nod); 832 } else { 833 regalloc(&nod, r, nn); 834 cgen(r, &nod); 835 regalloc(&nod1, l, Z); 836 cgen(l, &nod1); 837 } 838 gopcode(o, &nod1, &nod, Z); 839 regfree(&nod); 840 regfree(&nod1); 841 842 com: 843 if(nn != Z) { 844 p1 = p; 845 gopcode(OAS, nodconst(1), Z, nn); 846 gbranch(OGOTO); 847 p2 = p; 848 patch(p1, pc); 849 gopcode(OAS, nodconst(0), Z, nn); 850 patch(p2, pc); 851 } 852 break; 853 } 854 cursafe = curs; 855 } 856 857 void 858 sugen(Node *n, Node *nn, long w) 859 { 860 Prog *p1; 861 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 862 Type *t; 863 long pc1; 864 int i, m, c; 865 866 if(n == Z || n->type == T) 867 return; 868 if(debug['g']) { 869 prtree(nn, "sugen lhs"); 870 prtree(n, "sugen"); 871 } 872 if(nn == nodrat) 873 if(w > nrathole) 874 nrathole = w; 875 switch(n->op) { 876 case OIND: 877 if(nn == Z) { 878 nullwarn(n->left, Z); 879 break; 880 } 881 882 default: 883 goto copy; 884 885 case OCONST: 886 if(n->type && typev[n->type->etype]) { 887 if(nn == Z) { 888 nullwarn(n->left, Z); 889 break; 890 } 891 892 t = nn->type; 893 nn->type = types[TLONG]; 894 reglcgen(&nod1, nn, Z); 895 nn->type = t; 896 897 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 898 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 899 else 900 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 901 nod1.xoffset += SZ_LONG; 902 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 903 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 904 else 905 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 906 907 regfree(&nod1); 908 break; 909 } 910 goto copy; 911 912 case ODOT: 913 l = n->left; 914 sugen(l, nodrat, l->type->width); 915 if(nn != Z) { 916 warn(n, "non-interruptable temporary"); 917 nod1 = *nodrat; 918 r = n->right; 919 if(!r || r->op != OCONST) { 920 diag(n, "DOT and no offset"); 921 break; 922 } 923 nod1.xoffset += (long)r->vconst; 924 nod1.type = n->type; 925 sugen(&nod1, nn, w); 926 } 927 break; 928 929 case OSTRUCT: 930 /* 931 * rewrite so lhs has no fn call 932 */ 933 if(nn != Z && nn->complex >= FNX) { 934 nod1 = *n; 935 nod1.type = typ(TIND, n->type); 936 regret(&nod2, &nod1); 937 lcgen(nn, &nod2); 938 regsalloc(&nod0, &nod1); 939 gopcode(OAS, &nod2, Z, &nod0); 940 regfree(&nod2); 941 942 nod1 = *n; 943 nod1.op = OIND; 944 nod1.left = &nod0; 945 nod1.right = Z; 946 nod1.complex = 1; 947 948 sugen(n, &nod1, w); 949 return; 950 } 951 952 r = n->left; 953 for(t = n->type->link; t != T; t = t->down) { 954 l = r; 955 if(r->op == OLIST) { 956 l = r->left; 957 r = r->right; 958 } 959 if(nn == Z) { 960 cgen(l, nn); 961 continue; 962 } 963 /* 964 * hand craft *(&nn + o) = l 965 */ 966 nod0 = znode; 967 nod0.op = OAS; 968 nod0.type = t; 969 nod0.left = &nod1; 970 nod0.right = l; 971 972 nod1 = znode; 973 nod1.op = OIND; 974 nod1.type = t; 975 nod1.left = &nod2; 976 977 nod2 = znode; 978 nod2.op = OADD; 979 nod2.type = typ(TIND, t); 980 nod2.left = &nod3; 981 nod2.right = &nod4; 982 983 nod3 = znode; 984 nod3.op = OADDR; 985 nod3.type = nod2.type; 986 nod3.left = nn; 987 988 nod4 = znode; 989 nod4.op = OCONST; 990 nod4.type = nod2.type; 991 nod4.vconst = t->offset; 992 993 ccom(&nod0); 994 acom(&nod0); 995 xcom(&nod0); 996 nod0.addable = 0; 997 998 cgen(&nod0, Z); 999 } 1000 break; 1001 1002 case OAS: 1003 if(nn == Z) { 1004 if(n->addable < INDEXED) 1005 sugen(n->right, n->left, w); 1006 break; 1007 } 1008 sugen(n->right, nodrat, w); 1009 warn(n, "non-interruptable temporary"); 1010 sugen(nodrat, n->left, w); 1011 sugen(nodrat, nn, w); 1012 break; 1013 1014 case OFUNC: 1015 if(nn == Z) { 1016 sugen(n, nodrat, w); 1017 break; 1018 } 1019 if(nn->op != OIND) { 1020 nn = new1(OADDR, nn, Z); 1021 nn->type = types[TIND]; 1022 nn->addable = 0; 1023 } else 1024 nn = nn->left; 1025 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 1026 n->type = types[TVOID]; 1027 n->left->type = types[TVOID]; 1028 cgen(n, Z); 1029 break; 1030 1031 case OCOND: 1032 bcgen(n->left, 1); 1033 p1 = p; 1034 sugen(n->right->left, nn, w); 1035 gbranch(OGOTO); 1036 patch(p1, pc); 1037 p1 = p; 1038 sugen(n->right->right, nn, w); 1039 patch(p1, pc); 1040 break; 1041 1042 case OCOMMA: 1043 cgen(n->left, Z); 1044 sugen(n->right, nn, w); 1045 break; 1046 } 1047 return; 1048 1049 copy: 1050 if(nn == Z) 1051 return; 1052 if(n->complex >= FNX && nn->complex >= FNX) { 1053 t = nn->type; 1054 nn->type = types[TLONG]; 1055 regialloc(&nod1, nn, Z); 1056 lcgen(nn, &nod1); 1057 regsalloc(&nod2, nn); 1058 nn->type = t; 1059 1060 gopcode(OAS, &nod1, Z, &nod2); 1061 regfree(&nod1); 1062 1063 nod2.type = typ(TIND, t); 1064 1065 nod1 = nod2; 1066 nod1.op = OIND; 1067 nod1.left = &nod2; 1068 nod1.right = Z; 1069 nod1.complex = 1; 1070 nod1.type = t; 1071 1072 sugen(n, &nod1, w); 1073 return; 1074 } 1075 1076 if(n->complex > nn->complex) { 1077 t = n->type; 1078 n->type = types[TLONG]; 1079 reglcgen(&nod1, n, Z); 1080 n->type = t; 1081 1082 t = nn->type; 1083 nn->type = types[TLONG]; 1084 reglcgen(&nod2, nn, Z); 1085 nn->type = t; 1086 } else { 1087 t = nn->type; 1088 nn->type = types[TLONG]; 1089 reglcgen(&nod2, nn, Z); 1090 nn->type = t; 1091 1092 t = n->type; 1093 n->type = types[TLONG]; 1094 reglcgen(&nod1, n, Z); 1095 n->type = t; 1096 } 1097 1098 w /= SZ_LONG; 1099 if(w <= 5) { 1100 layout(&nod1, &nod2, w, 0, Z); 1101 goto out; 1102 } 1103 1104 /* 1105 * minimize space for unrolling loop 1106 * 3,4,5 times. (6 or more is never minimum) 1107 * if small structure, try 2 also. 1108 */ 1109 c = 0; /* set */ 1110 m = 100; 1111 i = 3; 1112 if(w <= 15) 1113 i = 2; 1114 for(; i<=5; i++) 1115 if(i + w%i <= m) { 1116 c = i; 1117 m = c + w%c; 1118 } 1119 1120 regalloc(&nod3, ®node, Z); 1121 layout(&nod1, &nod2, w%c, w/c, &nod3); 1122 1123 pc1 = pc; 1124 layout(&nod1, &nod2, c, 0, Z); 1125 1126 gopcode(OSUB, nodconst(1), Z, &nod3); 1127 nod1.op = OREGISTER; 1128 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1); 1129 nod2.op = OREGISTER; 1130 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2); 1131 1132 gopcode(OEQ, &nod3, Z, Z); 1133 p->as = ABGTZ; 1134 patch(p, pc1); 1135 1136 regfree(&nod3); 1137 out: 1138 regfree(&nod1); 1139 regfree(&nod2); 1140 } 1141 1142 void 1143 layout(Node *f, Node *t, int c, int cv, Node *cn) 1144 { 1145 Node t1, t2; 1146 1147 while(c > 3) { 1148 layout(f, t, 2, 0, Z); 1149 c -= 2; 1150 } 1151 1152 regalloc(&t1, ®node, Z); 1153 regalloc(&t2, ®node, Z); 1154 t1.type = types[TLONG]; 1155 t2.type = types[TLONG]; 1156 if(c > 0) { 1157 gopcode(OAS, f, Z, &t1); 1158 f->xoffset += SZ_LONG; 1159 } 1160 if(cn != Z) 1161 gopcode(OAS, nodconst(cv), Z, cn); 1162 if(c > 1) { 1163 gopcode(OAS, f, Z, &t2); 1164 f->xoffset += SZ_LONG; 1165 } 1166 if(c > 0) { 1167 gopcode(OAS, &t1, Z, t); 1168 t->xoffset += SZ_LONG; 1169 } 1170 if(c > 2) { 1171 gopcode(OAS, f, Z, &t1); 1172 f->xoffset += SZ_LONG; 1173 } 1174 if(c > 1) { 1175 gopcode(OAS, &t2, Z, t); 1176 t->xoffset += SZ_LONG; 1177 } 1178 if(c > 2) { 1179 gopcode(OAS, &t1, Z, t); 1180 t->xoffset += SZ_LONG; 1181 } 1182 regfree(&t1); 1183 regfree(&t2); 1184 } 1185