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