1 #include "gc.h" 2 3 static void cmpv(Node*, int, Node*); 4 static void testv(Node*, int); 5 static void cgen64(Node*, Node*); 6 static int isvconstable(int, vlong); 7 8 void 9 cgen(Node *n, Node *nn) 10 { 11 Node *l, *r; 12 Prog *p1; 13 Node nod, nod1, nod2, nod3, nod4; 14 int o; 15 long v, curs; 16 17 if(debug['g']) { 18 prtree(nn, "cgen lhs"); 19 prtree(n, "cgen"); 20 } 21 if(n == Z || n->type == T) 22 return; 23 if(typesu[n->type->etype]) { 24 sugen(n, nn, n->type->width); 25 return; 26 } 27 if(typev[n->type->etype]) { 28 switch(n->op) { 29 case OCONST: 30 case OFUNC: 31 cgen64(n, nn); 32 return; 33 } 34 } 35 l = n->left; 36 r = n->right; 37 o = n->op; 38 if(n->addable >= INDEXED) { 39 if(nn == Z) { 40 switch(o) { 41 default: 42 nullwarn(Z, Z); 43 break; 44 case OINDEX: 45 nullwarn(l, r); 46 break; 47 } 48 return; 49 } 50 gmove(n, nn); 51 return; 52 } 53 curs = cursafe; 54 55 if(n->complex >= FNX) 56 if(l->complex >= FNX) 57 if(r != Z && r->complex >= FNX) 58 switch(o) { 59 default: 60 if(!typev[r->type->etype]) { 61 regret(&nod, r); 62 cgen(r, &nod); 63 regsalloc(&nod1, r); 64 gmove(&nod, &nod1); 65 regfree(&nod); 66 } else { 67 regsalloc(&nod1, r); 68 cgen(r, &nod1); 69 } 70 71 nod = *n; 72 nod.right = &nod1; 73 cgen(&nod, nn); 74 return; 75 76 case OFUNC: 77 case OCOMMA: 78 case OANDAND: 79 case OOROR: 80 case OCOND: 81 case ODOT: 82 break; 83 } 84 85 switch(o) { 86 default: 87 diag(n, "unknown op in cgen: %O", o); 88 break; 89 90 case ONEG: 91 case OCOM: 92 if(nn == Z) { 93 nullwarn(l, Z); 94 break; 95 } 96 regalloc(&nod, l, nn); 97 cgen(l, &nod); 98 gopcode(o, &nod, Z, &nod); 99 gmove(&nod, nn); 100 regfree(&nod); 101 break; 102 103 case OAS: 104 if(l->op == OBIT) 105 goto bitas; 106 if(l->addable >= INDEXED) { 107 if(nn != Z || r->addable < INDEXED) { 108 regalloc(&nod, r, nn); 109 cgen(r, &nod); 110 gmove(&nod, l); 111 regfree(&nod); 112 } else 113 gmove(r, l); 114 break; 115 } 116 if(l->complex >= r->complex) { 117 reglcgen(&nod1, l, Z); 118 if(r->addable >= INDEXED) { 119 gmove(r, &nod1); 120 if(nn != Z) 121 gmove(r, nn); 122 regfree(&nod1); 123 break; 124 } 125 regalloc(&nod, r, nn); 126 cgen(r, &nod); 127 } else { 128 regalloc(&nod, r, nn); 129 cgen(r, &nod); 130 reglcgen(&nod1, l, Z); 131 } 132 gmove(&nod, &nod1); 133 regfree(&nod); 134 regfree(&nod1); 135 break; 136 137 bitas: 138 n = l->left; 139 regalloc(&nod, r, nn); 140 if(l->complex >= r->complex) { 141 reglcgen(&nod1, n, Z); 142 cgen(r, &nod); 143 } else { 144 cgen(r, &nod); 145 reglcgen(&nod1, n, Z); 146 } 147 regalloc(&nod2, n, Z); 148 gopcode(OAS, &nod1, Z, &nod2); 149 bitstore(l, &nod, &nod1, &nod2, nn); 150 break; 151 152 case OBIT: 153 if(nn == Z) { 154 nullwarn(l, Z); 155 break; 156 } 157 bitload(n, &nod, Z, Z, nn); 158 gopcode(OAS, &nod, Z, nn); 159 regfree(&nod); 160 break; 161 162 case OXOR: 163 if(nn != Z) 164 if(r->op == OCONST && r->vconst == -1){ 165 regalloc(&nod, l, nn); 166 cgen(l, &nod); 167 gopcode(OCOM, &nod, Z, &nod); 168 gmove(&nod, nn); 169 regfree(&nod); 170 break; 171 } 172 173 case OADD: 174 case OSUB: 175 case OAND: 176 case OOR: 177 case OLSHR: 178 case OASHL: 179 case OASHR: 180 /* 181 * immediate operands 182 */ 183 if(nn != Z && r->op == OCONST && !typefd[n->type->etype] && 184 (!typev[n->type->etype] || isvconstable(o, r->vconst))) { 185 regalloc(&nod, l, nn); 186 cgen(l, &nod); 187 if(o == OAND || r->vconst != 0) 188 gopcode(o, r, Z, &nod); 189 gmove(&nod, nn); 190 regfree(&nod); 191 break; 192 } 193 194 case OMUL: 195 case OLMUL: 196 case OLDIV: 197 case OLMOD: 198 case ODIV: 199 case OMOD: 200 if(nn == Z) { 201 nullwarn(l, r); 202 break; 203 } 204 if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) { 205 if(mulcon(n, nn)) 206 break; 207 if(debug['M']) 208 print("%L multiply\n", n->lineno); 209 } 210 if(l->complex >= r->complex) { 211 regalloc(&nod, l, nn); 212 cgen(l, &nod); 213 if(o != OMUL || typev[n->type->etype] || !sconst(r)) { 214 regalloc(&nod1, r, Z); 215 cgen(r, &nod1); 216 gopcode(o, &nod1, Z, &nod); 217 regfree(&nod1); 218 } else 219 gopcode(o, r, Z, &nod); 220 } else { 221 regalloc(&nod1, r, nn); 222 cgen(r, &nod1); 223 regalloc(&nod, l, Z); 224 cgen(l, &nod); 225 gopcode(o, &nod1, Z, &nod); 226 regfree(&nod1); 227 } 228 gopcode(OAS, &nod, Z, nn); 229 regfree(&nod); 230 break; 231 232 case OASLSHR: 233 case OASASHL: 234 case OASASHR: 235 case OASAND: 236 case OASADD: 237 case OASSUB: 238 case OASXOR: 239 case OASOR: 240 if(l->op == OBIT) 241 goto asbitop; 242 if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] && 243 (!typev[n->type->etype] || isvconstable(o, r->vconst))) { 244 if(l->addable < INDEXED) 245 reglcgen(&nod2, l, Z); 246 else 247 nod2 = *l; 248 regalloc(&nod, l, nn); 249 gopcode(OAS, &nod2, Z, &nod); 250 gopcode(o, r, Z, &nod); 251 gopcode(OAS, &nod, Z, &nod2); 252 253 regfree(&nod); 254 if(l->addable < INDEXED) 255 regfree(&nod2); 256 break; 257 } 258 259 case OASLMUL: 260 case OASLDIV: 261 case OASLMOD: 262 case OASMUL: 263 case OASDIV: 264 case OASMOD: 265 if(l->op == OBIT) 266 goto asbitop; 267 if(l->complex >= r->complex) { 268 if(l->addable < INDEXED) 269 reglcgen(&nod2, l, Z); 270 else 271 nod2 = *l; 272 regalloc(&nod, r, Z); 273 cgen(r, &nod); 274 } else { 275 regalloc(&nod, r, Z); 276 cgen(r, &nod); 277 if(l->addable < INDEXED) 278 reglcgen(&nod2, l, Z); 279 else 280 nod2 = *l; 281 } 282 regalloc(&nod1, n, nn); 283 gopcode(OAS, &nod2, Z, &nod1); 284 gopcode(o, &nod, Z, &nod1); 285 gopcode(OAS, &nod1, Z, &nod2); 286 if(nn != Z) 287 gopcode(OAS, &nod1, 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 regalloc(&nod3, r, Z); 297 if(l->complex >= r->complex) { 298 bitload(l, &nod, &nod1, &nod2, &nod4); 299 cgen(r, &nod3); 300 } else { 301 cgen(r, &nod3); 302 bitload(l, &nod, &nod1, &nod2, &nod4); 303 } 304 gmove(&nod, &nod4); 305 gopcode(n->op, &nod3, Z, &nod4); 306 regfree(&nod3); 307 gmove(&nod4, &nod); 308 regfree(&nod4); 309 bitstore(l, &nod, &nod1, &nod2, nn); 310 break; 311 312 case OADDR: 313 if(nn == Z) { 314 nullwarn(l, Z); 315 break; 316 } 317 lcgen(l, nn); 318 break; 319 320 case OFUNC: 321 if(l->complex >= FNX) { 322 if(l->op != OIND) 323 diag(n, "bad function call"); 324 325 regret(&nod, l->left); 326 cgen(l->left, &nod); 327 regsalloc(&nod1, l->left); 328 gopcode(OAS, &nod, Z, &nod1); 329 regfree(&nod); 330 331 nod = *n; 332 nod.left = &nod2; 333 nod2 = *l; 334 nod2.left = &nod1; 335 nod2.complex = 1; 336 cgen(&nod, nn); 337 338 return; 339 } 340 o = reg[REGARG]; 341 gargs(r, &nod, &nod1); 342 if(l->addable < INDEXED) { 343 reglcgen(&nod, l, Z); 344 gopcode(OFUNC, Z, Z, &nod); 345 regfree(&nod); 346 } else 347 gopcode(OFUNC, Z, Z, l); 348 if(REGARG) 349 if(o != reg[REGARG]) 350 reg[REGARG]--; 351 if(nn != Z) { 352 regret(&nod, n); 353 gopcode(OAS, &nod, Z, nn); 354 regfree(&nod); 355 } 356 break; 357 358 case OIND: 359 if(nn == Z) { 360 cgen(l, nn); 361 break; 362 } 363 regialloc(&nod, n, nn); 364 r = l; 365 while(r->op == OADD) 366 r = r->right; 367 if(sconst(r)) { 368 v = r->vconst; 369 r->vconst = 0; 370 cgen(l, &nod); 371 nod.xoffset += v; 372 r->vconst = v; 373 } else 374 cgen(l, &nod); 375 regind(&nod, n); 376 gmove(&nod, nn); 377 regfree(&nod); 378 break; 379 380 case OEQ: 381 case ONE: 382 case OLE: 383 case OLT: 384 case OGE: 385 case OGT: 386 case OLO: 387 case OLS: 388 case OHI: 389 case OHS: 390 if(nn == Z) { 391 nullwarn(l, r); 392 break; 393 } 394 boolgen(n, 1, nn); 395 break; 396 397 case OANDAND: 398 case OOROR: 399 boolgen(n, 1, nn); 400 if(nn == Z) 401 patch(p, pc); 402 break; 403 404 case ONOT: 405 if(nn == Z) { 406 nullwarn(l, Z); 407 break; 408 } 409 boolgen(n, 1, nn); 410 break; 411 412 case OCOMMA: 413 cgen(l, Z); 414 cgen(r, nn); 415 break; 416 417 case OCAST: 418 if(nn == Z) { 419 nullwarn(l, Z); 420 break; 421 } 422 /* 423 * convert from types l->n->nn 424 */ 425 if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { 426 /* both null, gen l->nn */ 427 cgen(l, nn); 428 break; 429 } 430 if(typev[l->type->etype] || typev[n->type->etype]) { 431 cgen64(n, nn); 432 break; 433 } 434 regalloc(&nod, l, nn); 435 cgen(l, &nod); 436 regalloc(&nod1, n, &nod); 437 gmove(&nod, &nod1); 438 gmove(&nod1, nn); 439 regfree(&nod1); 440 regfree(&nod); 441 break; 442 443 case ODOT: 444 sugen(l, nodrat, l->type->width); 445 if(nn != Z) { 446 warn(n, "non-interruptable temporary"); 447 nod = *nodrat; 448 if(!r || r->op != OCONST) { 449 diag(n, "DOT and no offset"); 450 break; 451 } 452 nod.xoffset += (long)r->vconst; 453 nod.type = n->type; 454 cgen(&nod, nn); 455 } 456 break; 457 458 case OCOND: 459 bcgen(l, 1); 460 p1 = p; 461 cgen(r->left, nn); 462 gbranch(OGOTO); 463 patch(p1, pc); 464 p1 = p; 465 cgen(r->right, nn); 466 patch(p1, pc); 467 break; 468 469 case OPOSTINC: 470 case OPOSTDEC: 471 v = 1; 472 if(l->type->etype == TIND) 473 v = l->type->link->width; 474 if(o == OPOSTDEC) 475 v = -v; 476 if(l->op == OBIT) 477 goto bitinc; 478 if(nn == Z) 479 goto pre; 480 481 if(l->addable < INDEXED) 482 reglcgen(&nod2, l, Z); 483 else 484 nod2 = *l; 485 486 regalloc(&nod, l, nn); 487 gopcode(OAS, &nod2, Z, &nod); 488 regalloc(&nod1, l, Z); 489 if(typefd[l->type->etype]) { 490 regalloc(&nod3, l, Z); 491 if(v < 0) { 492 gopcode(OAS, nodfconst(-v), Z, &nod3); 493 gopcode(OSUB, &nod3, &nod, &nod1); 494 } else { 495 gopcode(OAS, nodfconst(v), Z, &nod3); 496 gopcode(OADD, &nod3, &nod, &nod1); 497 } 498 regfree(&nod3); 499 } else 500 gopcode(OADD, nodconst(v), &nod, &nod1); 501 gopcode(OAS, &nod1, Z, &nod2); 502 503 regfree(&nod); 504 regfree(&nod1); 505 if(l->addable < INDEXED) 506 regfree(&nod2); 507 break; 508 509 case OPREINC: 510 case OPREDEC: 511 v = 1; 512 if(l->type->etype == TIND) 513 v = l->type->link->width; 514 if(o == OPREDEC) 515 v = -v; 516 if(l->op == OBIT) 517 goto bitinc; 518 519 pre: 520 if(l->addable < INDEXED) 521 reglcgen(&nod2, l, Z); 522 else 523 nod2 = *l; 524 525 regalloc(&nod, l, nn); 526 gopcode(OAS, &nod2, Z, &nod); 527 if(typefd[l->type->etype]) { 528 regalloc(&nod3, l, Z); 529 if(v < 0) { 530 gopcode(OAS, nodfconst(-v), Z, &nod3); 531 gopcode(OSUB, &nod3, Z, &nod); 532 } else { 533 gopcode(OAS, nodfconst(v), Z, &nod3); 534 gopcode(OADD, &nod3, Z, &nod); 535 } 536 regfree(&nod3); 537 } else 538 gopcode(OADD, nodconst(v), Z, &nod); 539 gopcode(OAS, &nod, Z, &nod2); 540 if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ 541 gins(ANOP, l, Z); 542 543 regfree(&nod); 544 if(l->addable < INDEXED) 545 regfree(&nod2); 546 break; 547 548 bitinc: 549 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 550 bitload(l, &nod, &nod1, &nod2, Z); 551 gopcode(OAS, &nod, Z, nn); 552 gopcode(OADD, nodconst(v), Z, &nod); 553 bitstore(l, &nod, &nod1, &nod2, Z); 554 break; 555 } 556 bitload(l, &nod, &nod1, &nod2, nn); 557 gopcode(OADD, nodconst(v), Z, &nod); 558 bitstore(l, &nod, &nod1, &nod2, nn); 559 break; 560 } 561 cursafe = curs; 562 } 563 564 void 565 reglcgen(Node *t, Node *n, Node *nn) 566 { 567 Node *r; 568 long v; 569 570 regialloc(t, n, nn); 571 if(n->op == OIND) { 572 r = n->left; 573 while(r->op == OADD) 574 r = r->right; 575 if(sconst(r)) { 576 v = r->vconst; 577 r->vconst = 0; 578 lcgen(n, t); 579 t->xoffset += v; 580 r->vconst = v; 581 regind(t, n); 582 return; 583 } 584 } 585 lcgen(n, t); 586 regind(t, n); 587 } 588 589 void 590 lcgen(Node *n, Node *nn) 591 { 592 Prog *p1; 593 Node nod; 594 595 if(debug['g']) { 596 prtree(nn, "lcgen lhs"); 597 prtree(n, "lcgen"); 598 } 599 if(n == Z || n->type == T) 600 return; 601 if(nn == Z) { 602 nn = &nod; 603 regalloc(&nod, n, Z); 604 } 605 switch(n->op) { 606 default: 607 if(n->addable < INDEXED) { 608 diag(n, "unknown op in lcgen: %O", n->op); 609 break; 610 } 611 nod = *n; 612 nod.op = OADDR; 613 nod.left = n; 614 nod.right = Z; 615 nod.type = types[TIND]; 616 gopcode(OAS, &nod, Z, nn); 617 break; 618 619 case OCOMMA: 620 cgen(n->left, n->left); 621 lcgen(n->right, nn); 622 break; 623 624 case OIND: 625 cgen(n->left, nn); 626 break; 627 628 case OCOND: 629 bcgen(n->left, 1); 630 p1 = p; 631 lcgen(n->right->left, nn); 632 gbranch(OGOTO); 633 patch(p1, pc); 634 p1 = p; 635 lcgen(n->right->right, nn); 636 patch(p1, pc); 637 break; 638 } 639 } 640 641 void 642 bcgen(Node *n, int true) 643 { 644 645 if(n->type == T) 646 gbranch(OGOTO); 647 else 648 boolgen(n, true, Z); 649 } 650 651 void 652 boolgen(Node *n, int true, Node *nn) 653 { 654 int o, uns; 655 Prog *p1, *p2; 656 Node *l, *r, nod, nod1; 657 long curs; 658 659 if(debug['g']) { 660 prtree(nn, "boolgen lhs"); 661 prtree(n, "boolgen"); 662 } 663 uns = 0; 664 curs = cursafe; 665 l = n->left; 666 r = n->right; 667 switch(n->op) { 668 669 default: 670 if(n->op == OCONST) { 671 o = vconst(n); 672 if(!true) 673 o = !o; 674 gbranch(OGOTO); 675 if(o) { 676 p1 = p; 677 gbranch(OGOTO); 678 patch(p1, pc); 679 } 680 goto com; 681 } 682 if(typev[n->type->etype]) { 683 testv(n, true); 684 goto com; 685 } 686 regalloc(&nod, n, nn); 687 cgen(n, &nod); 688 o = ONE; 689 if(true) 690 o = comrel[relindex(o)]; 691 if(typefd[n->type->etype]) { 692 nodreg(&nod1, n, NREG+FREGZERO); 693 gopcode(o, &nod, Z, &nod1); 694 } else 695 gopcode(o, &nod, Z, nodconst(0)); 696 regfree(&nod); 697 goto com; 698 699 case OCOMMA: 700 cgen(l, Z); 701 boolgen(r, true, nn); 702 break; 703 704 case ONOT: 705 boolgen(l, !true, nn); 706 break; 707 708 case OCOND: 709 bcgen(l, 1); 710 p1 = p; 711 bcgen(r->left, true); 712 p2 = p; 713 gbranch(OGOTO); 714 patch(p1, pc); 715 p1 = p; 716 bcgen(r->right, !true); 717 patch(p2, pc); 718 p2 = p; 719 gbranch(OGOTO); 720 patch(p1, pc); 721 patch(p2, pc); 722 goto com; 723 724 case OANDAND: 725 if(!true) 726 goto caseor; 727 728 caseand: 729 bcgen(l, true); 730 p1 = p; 731 bcgen(r, !true); 732 p2 = p; 733 patch(p1, pc); 734 gbranch(OGOTO); 735 patch(p2, pc); 736 goto com; 737 738 case OOROR: 739 if(!true) 740 goto caseand; 741 742 caseor: 743 bcgen(l, !true); 744 p1 = p; 745 bcgen(r, !true); 746 p2 = p; 747 gbranch(OGOTO); 748 patch(p1, pc); 749 patch(p2, pc); 750 goto com; 751 752 case OHI: 753 case OHS: 754 case OLO: 755 case OLS: 756 uns = 1; 757 /* fall through */ 758 case OEQ: 759 case ONE: 760 case OLE: 761 case OLT: 762 case OGE: 763 case OGT: 764 if(typev[l->type->etype]){ 765 cmpv(n, true, Z); 766 goto com; 767 } 768 o = n->op; 769 if(true) 770 o = comrel[relindex(o)]; 771 if(l->complex >= FNX && r->complex >= FNX) { 772 regret(&nod, r); 773 cgen(r, &nod); 774 regsalloc(&nod1, r); 775 gopcode(OAS, &nod, Z, &nod1); 776 regfree(&nod); 777 nod = *n; 778 nod.right = &nod1; 779 boolgen(&nod, true, nn); 780 break; 781 } 782 if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) { 783 regalloc(&nod, l, nn); 784 cgen(l, &nod); 785 gopcode(o, &nod, Z, r); 786 regfree(&nod); 787 goto com; 788 } 789 if(l->complex >= r->complex) { 790 regalloc(&nod1, l, nn); 791 cgen(l, &nod1); 792 regalloc(&nod, r, Z); 793 cgen(r, &nod); 794 } else { 795 regalloc(&nod, r, nn); 796 cgen(r, &nod); 797 regalloc(&nod1, l, Z); 798 cgen(l, &nod1); 799 } 800 gopcode(o, &nod1, Z, &nod); 801 regfree(&nod); 802 regfree(&nod1); 803 804 com: 805 if(nn != Z) { 806 p1 = p; 807 gopcode(OAS, nodconst(1L), Z, nn); 808 gbranch(OGOTO); 809 p2 = p; 810 patch(p1, pc); 811 gopcode(OAS, nodconst(0L), Z, nn); 812 patch(p2, pc); 813 } 814 break; 815 } 816 cursafe = curs; 817 } 818 819 void 820 sugen(Node *n, Node *nn, long w) 821 { 822 Prog *p1; 823 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 824 Type *t; 825 long pc1; 826 int i, m, c; 827 828 if(n == Z || n->type == T) 829 return; 830 if(nn == nodrat) 831 if(w > nrathole) 832 nrathole = w; 833 if(debug['g']) { 834 prtree(nn, "sugen lhs"); 835 prtree(n, "sugen"); 836 } 837 if(typev[n->type->etype]) { 838 diag(n, "old vlong sugen: %O", n->op); 839 return; 840 } 841 switch(n->op) { 842 case OIND: 843 if(nn == Z) { 844 nullwarn(n->left, Z); 845 break; 846 } 847 848 default: 849 goto copy; 850 851 case ODOT: 852 l = n->left; 853 sugen(l, nodrat, l->type->width); 854 if(nn != Z) { 855 warn(n, "non-interruptable temporary"); 856 nod1 = *nodrat; 857 r = n->right; 858 if(!r || r->op != OCONST) { 859 diag(n, "DOT and no offset"); 860 break; 861 } 862 nod1.xoffset += (long)r->vconst; 863 nod1.type = n->type; 864 sugen(&nod1, nn, w); 865 } 866 break; 867 868 case OSTRUCT: 869 /* 870 * rewrite so lhs has no side effects 871 */ 872 if(nn != Z && side(nn)) { 873 nod1 = *n; 874 nod1.type = typ(TIND, n->type); 875 regalloc(&nod2, &nod1, Z); 876 lcgen(nn, &nod2); 877 regsalloc(&nod0, &nod1); 878 gopcode(OAS, &nod2, Z, &nod0); 879 regfree(&nod2); 880 881 nod1 = *n; 882 nod1.op = OIND; 883 nod1.left = &nod0; 884 nod1.right = Z; 885 nod1.complex = 1; 886 887 sugen(n, &nod1, w); 888 return; 889 } 890 891 r = n->left; 892 for(t = n->type->link; t != T; t = t->down) { 893 l = r; 894 if(r->op == OLIST) { 895 l = r->left; 896 r = r->right; 897 } 898 if(nn == Z) { 899 cgen(l, nn); 900 continue; 901 } 902 /* 903 * hand craft *(&nn + o) = l 904 */ 905 nod0 = znode; 906 nod0.op = OAS; 907 nod0.type = t; 908 nod0.left = &nod1; 909 nod0.right = l; 910 911 nod1 = znode; 912 nod1.op = OIND; 913 nod1.type = t; 914 nod1.left = &nod2; 915 916 nod2 = znode; 917 nod2.op = OADD; 918 nod2.type = typ(TIND, t); 919 nod2.left = &nod3; 920 nod2.right = &nod4; 921 922 nod3 = znode; 923 nod3.op = OADDR; 924 nod3.type = nod2.type; 925 nod3.left = nn; 926 927 nod4 = znode; 928 nod4.op = OCONST; 929 nod4.type = nod2.type; 930 nod4.vconst = t->offset; 931 932 ccom(&nod0); 933 acom(&nod0); 934 xcom(&nod0); 935 nod0.addable = 0; 936 937 /* prtree(&nod0, "hand craft"); /* */ 938 cgen(&nod0, Z); 939 } 940 break; 941 942 case OAS: 943 if(nn == Z) { 944 if(n->addable < INDEXED) 945 sugen(n->right, n->left, w); 946 break; 947 } 948 /* BOTCH -- functions can clobber rathole */ 949 sugen(n->right, nodrat, w); 950 warn(n, "non-interruptable temporary"); 951 sugen(nodrat, n->left, w); 952 sugen(nodrat, nn, w); 953 break; 954 955 case OFUNC: 956 /* this transformation should probably be done earlier */ 957 if(nn == Z) { 958 sugen(n, nodrat, w); 959 break; 960 } 961 if(nn->op != OIND) { 962 nn = new1(OADDR, nn, Z); 963 nn->type = types[TIND]; 964 nn->addable = 0; 965 } else 966 nn = nn->left; 967 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 968 n->complex = FNX; 969 n->type = types[TVOID]; 970 n->left->type = types[TVOID]; 971 cgen(n, Z); 972 break; 973 974 case OCOND: 975 bcgen(n->left, 1); 976 p1 = p; 977 sugen(n->right->left, nn, w); 978 gbranch(OGOTO); 979 patch(p1, pc); 980 p1 = p; 981 sugen(n->right->right, nn, w); 982 patch(p1, pc); 983 break; 984 985 case OCOMMA: 986 cgen(n->left, Z); 987 sugen(n->right, nn, w); 988 break; 989 } 990 return; 991 992 copy: 993 if(nn == Z) 994 return; 995 if(n->complex >= FNX && nn->complex >= FNX) { 996 t = nn->type; 997 nn->type = types[TLONG]; 998 regialloc(&nod1, nn, Z); 999 lcgen(nn, &nod1); 1000 regsalloc(&nod2, nn); 1001 nn->type = t; 1002 1003 gmove(&nod1, &nod2); 1004 regfree(&nod1); 1005 1006 nod2.type = typ(TIND, t); 1007 1008 nod1 = nod2; 1009 nod1.op = OIND; 1010 nod1.left = &nod2; 1011 nod1.right = Z; 1012 nod1.complex = 1; 1013 nod1.type = t; 1014 1015 sugen(n, &nod1, w); 1016 return; 1017 } 1018 1019 if(n->complex > nn->complex) { 1020 t = n->type; 1021 n->type = types[TLONG]; 1022 reglcgen(&nod1, n, Z); 1023 n->type = t; 1024 1025 t = nn->type; 1026 nn->type = types[TLONG]; 1027 reglcgen(&nod2, nn, Z); 1028 nn->type = t; 1029 } else { 1030 t = nn->type; 1031 nn->type = types[TLONG]; 1032 reglcgen(&nod2, nn, Z); 1033 nn->type = t; 1034 1035 t = n->type; 1036 n->type = types[TLONG]; 1037 reglcgen(&nod1, n, Z); 1038 n->type = t; 1039 } 1040 1041 w /= SZ_LONG; 1042 if(w <= 5) { 1043 layout(&nod1, &nod2, w, 0, Z); 1044 goto out; 1045 } 1046 1047 /* 1048 * minimize space for unrolling loop 1049 * 3,4,5 times. (6 or more is never minimum) 1050 * if small structure, try 2 also. 1051 */ 1052 c = 0; /* set */ 1053 m = 100; 1054 i = 3; 1055 if(w <= 15) 1056 i = 2; 1057 for(; i<=5; i++) 1058 if(i + w%i <= m) { 1059 c = i; 1060 m = c + w%c; 1061 } 1062 1063 regalloc(&nod3, ®node, Z); 1064 layout(&nod1, &nod2, w%c, w/c, &nod3); 1065 1066 pc1 = pc; 1067 layout(&nod1, &nod2, c, 0, Z); 1068 1069 gopcode(OSUB, nodconst(1L), Z, &nod3); 1070 nod1.op = OREGISTER; 1071 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1); 1072 nod2.op = OREGISTER; 1073 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2); 1074 1075 gopcode(OGT, &nod3, Z, nodconst(0)); 1076 patch(p, pc1); 1077 1078 regfree(&nod3); 1079 out: 1080 regfree(&nod1); 1081 regfree(&nod2); 1082 } 1083 1084 void 1085 layout(Node *f, Node *t, int c, int cv, Node *cn) 1086 { 1087 Node t1, t2; 1088 1089 while(c > 3) { 1090 layout(f, t, 2, 0, Z); 1091 c -= 2; 1092 } 1093 1094 regalloc(&t1, ®node, Z); 1095 regalloc(&t2, ®node, Z); 1096 if(c > 0) { 1097 gopcode(OAS, f, Z, &t1); 1098 f->xoffset += SZ_LONG; 1099 } 1100 if(cn != Z) 1101 gopcode(OAS, nodconst(cv), Z, cn); 1102 if(c > 1) { 1103 gopcode(OAS, f, Z, &t2); 1104 f->xoffset += SZ_LONG; 1105 } 1106 if(c > 0) { 1107 gopcode(OAS, &t1, Z, t); 1108 t->xoffset += SZ_LONG; 1109 } 1110 if(c > 2) { 1111 gopcode(OAS, f, Z, &t1); 1112 f->xoffset += SZ_LONG; 1113 } 1114 if(c > 1) { 1115 gopcode(OAS, &t2, Z, t); 1116 t->xoffset += SZ_LONG; 1117 } 1118 if(c > 2) { 1119 gopcode(OAS, &t1, Z, t); 1120 t->xoffset += SZ_LONG; 1121 } 1122 regfree(&t1); 1123 regfree(&t2); 1124 } 1125 1126 /* 1127 * is the vlong's value directly addressible? 1128 */ 1129 int 1130 isvdirect(Node *n) 1131 { 1132 return n->op == ONAME || n->op == OCONST || n->op == OINDREG; 1133 } 1134 1135 /* 1136 * can the constant be used with given vlong op? 1137 */ 1138 static int 1139 isvconstable(int o, vlong v) 1140 { 1141 switch(o) { 1142 case OADD: 1143 case OASADD: 1144 /* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */ 1145 return v == 0 || v == -1; 1146 case OAND: 1147 case OOR: 1148 case OXOR: 1149 case OLSHR: 1150 case OASHL: 1151 case OASHR: 1152 case OASLSHR: 1153 case OASASHL: 1154 case OASASHR: 1155 return 1; 1156 } 1157 return 0; 1158 } 1159 1160 /* 1161 * most 64-bit operations: cgen into a register pair, then operate. 1162 * 64-bit comparisons are handled a little differently because the two underlying 1163 * comparisons can be compiled separately, since the calculations don't interact. 1164 */ 1165 1166 static void 1167 vcgen(Node *n, Node *o, int *f) 1168 { 1169 *f = 0; 1170 if(!isvdirect(n)) { 1171 if(n->complex >= FNX) { 1172 regsalloc(o, n); 1173 cgen(n, o); 1174 return; 1175 } 1176 *f = 1; 1177 if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) { 1178 regalloc(o, n, Z); 1179 cgen(n, o); 1180 } else 1181 reglcgen(o, n, Z); 1182 } else 1183 *o = *n; 1184 } 1185 1186 static int 1187 isuns(int op) 1188 { 1189 switch(op){ 1190 case OLO: 1191 case OLS: 1192 case OHI: 1193 case OHS: 1194 return 1; 1195 default: 1196 return 0; 1197 } 1198 } 1199 1200 static void 1201 gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op) 1202 { 1203 Node vl, vr; 1204 1205 regalloc(&vl, ®node, Z); 1206 mov(l, &vl, 0); 1207 regalloc(&vr, ®node, Z); 1208 mov(r, &vr, 1+isuns(op)); 1209 gopcode(op, &vl, Z, &vr); 1210 if(vl.op == OREGISTER) 1211 regfree(&vl); 1212 if(vr.op == OREGISTER) 1213 regfree(&vr); 1214 } 1215 1216 static void 1217 brcondv(Node *l, Node *r, int chi, int clo) 1218 { 1219 Prog *p1, *p2, *p3, *p4; 1220 1221 gcmpv(l, r, gloadhi, chi); 1222 p1 = p; 1223 gins(ABNE, Z, Z); 1224 p2 = p; 1225 gcmpv(l, r, gloadlo, clo); 1226 p3 = p; 1227 gbranch(OGOTO); 1228 p4 = p; 1229 patch(p1, pc); 1230 patch(p3, pc); 1231 gbranch(OGOTO); 1232 patch(p2, pc); 1233 patch(p4, pc); 1234 } 1235 1236 static void 1237 testv(Node *n, int true) 1238 { 1239 Node nod; 1240 1241 nod = znode; 1242 nod.op = ONE; 1243 nod.left = n; 1244 nod.right = new1(0, Z, Z); 1245 *nod.right = *nodconst(0); 1246 nod.right->type = n->type; 1247 nod.type = types[TLONG]; 1248 cmpv(&nod, true, Z); 1249 } 1250 1251 /* 1252 * comparison for vlong does high and low order parts separately, 1253 * which saves loading the latter if the high order comparison suffices 1254 */ 1255 static void 1256 cmpv(Node *n, int true, Node *nn) 1257 { 1258 Node *l, *r, nod, nod1; 1259 int o, f1, f2; 1260 Prog *p1, *p2; 1261 long curs; 1262 1263 if(debug['g']) { 1264 if(nn != nil) 1265 prtree(nn, "cmpv lhs"); 1266 prtree(n, "cmpv"); 1267 } 1268 curs = cursafe; 1269 l = n->left; 1270 r = n->right; 1271 if(l->complex >= FNX && r->complex >= FNX) { 1272 regsalloc(&nod1, r); 1273 cgen(r, &nod1); 1274 nod = *n; 1275 nod.right = &nod1; 1276 cmpv(&nod, true, nn); 1277 cursafe = curs; 1278 return; 1279 } 1280 if(l->complex >= r->complex) { 1281 vcgen(l, &nod1, &f1); 1282 vcgen(r, &nod, &f2); 1283 } else { 1284 vcgen(r, &nod, &f2); 1285 vcgen(l, &nod1, &f1); 1286 } 1287 nod.type = types[TLONG]; 1288 nod1.type = types[TLONG]; 1289 o = n->op; 1290 if(true) 1291 o = comrel[relindex(o)]; 1292 switch(o){ 1293 case OEQ: 1294 gcmpv(&nod1, &nod, gloadhi, ONE); 1295 p1 = p; 1296 gcmpv(&nod1, &nod, gloadlo, ONE); 1297 p2 = p; 1298 gbranch(OGOTO); 1299 patch(p1, pc); 1300 patch(p2, pc); 1301 break; 1302 case ONE: 1303 gcmpv(&nod1, &nod, gloadhi, ONE); 1304 p1 = p; 1305 gcmpv(&nod1, &nod, gloadlo, OEQ); 1306 p2 = p; 1307 patch(p1, pc); 1308 gbranch(OGOTO); 1309 patch(p2, pc); 1310 break; 1311 case OLE: 1312 brcondv(&nod1, &nod, OLT, OLS); 1313 break; 1314 case OGT: 1315 brcondv(&nod1, &nod, OGT, OHI); 1316 break; 1317 case OLS: 1318 brcondv(&nod1, &nod, OLO, OLS); 1319 break; 1320 case OHI: 1321 brcondv(&nod1, &nod, OHI, OHI); 1322 break; 1323 case OLT: 1324 brcondv(&nod1, &nod, OLT, OLO); 1325 break; 1326 case OGE: 1327 brcondv(&nod1, &nod, OGT, OHS); 1328 break; 1329 case OLO: 1330 brcondv(&nod1, &nod, OLO, OLO); 1331 break; 1332 case OHS: 1333 brcondv(&nod1, &nod, OHI, OHS); 1334 break; 1335 default: 1336 diag(n, "bad cmpv"); 1337 return; 1338 } 1339 if(f1) 1340 regfree(&nod1); 1341 if(f2) 1342 regfree(&nod); 1343 cursafe = curs; 1344 } 1345 1346 static void 1347 cgen64(Node *n, Node *nn) 1348 { 1349 Node *l, *r, *d; 1350 Node nod, nod1; 1351 long curs; 1352 Type *t; 1353 int o, m; 1354 1355 curs = cursafe; 1356 l = n->left; 1357 r = n->right; 1358 o = n->op; 1359 switch(o) { 1360 1361 case OCONST: 1362 if(nn == Z) { 1363 nullwarn(n->left, Z); 1364 break; 1365 } 1366 if(nn->op != OREGPAIR) { 1367 //prtree(n, "cgen64 const"); 1368 t = nn->type; 1369 nn->type = types[TLONG]; 1370 reglcgen(&nod1, nn, Z); 1371 nn->type = t; 1372 1373 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 1374 gmove(nod32const(n->vconst>>32), &nod1); 1375 else 1376 gmove(nod32const(n->vconst), &nod1); 1377 nod1.xoffset += SZ_LONG; 1378 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 1379 gmove(nod32const(n->vconst), &nod1); 1380 else 1381 gmove(nod32const(n->vconst>>32), &nod1); 1382 1383 regfree(&nod1); 1384 } else 1385 gmove(n, nn); 1386 break; 1387 1388 case OCAST: 1389 /* 1390 * convert from types l->n->nn 1391 */ 1392 if(typev[l->type->etype]){ 1393 /* vlong to non-vlong */ 1394 if(!isvdirect(l)) { 1395 if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) { 1396 regalloc(&nod, l, l); 1397 cgen(l, &nod); 1398 regalloc(&nod1, n, nn); 1399 gmove(nod.right, &nod1); 1400 } else { 1401 reglcgen(&nod, l, Z); 1402 regalloc(&nod1, n, nn); 1403 gloadlo(&nod, &nod1, 0); /* TO DO: not correct for typefd */ 1404 } 1405 regfree(&nod); 1406 } else { 1407 regalloc(&nod1, n, nn); 1408 gloadlo(l, &nod1, 0); /* TO DO: not correct for typefd */ 1409 } 1410 }else{ 1411 /* non-vlong to vlong */ 1412 regalloc(&nod, l, Z); 1413 cgen(l, &nod); 1414 regalloc(&nod1, n, nn); 1415 gmove(&nod, nod1.right); 1416 if(typeu[l->type->etype]) 1417 gmove(nodconst(0), nod1.left); 1418 else 1419 gopcode(OASHR, nodconst(31), nod1.right, nod1.left); 1420 regfree(&nod); 1421 } 1422 gmove(&nod1, nn); 1423 regfree(&nod1); 1424 break; 1425 1426 case OFUNC: 1427 /* this transformation should probably be done earlier */ 1428 if(nn == Z) { 1429 regsalloc(&nod1, n); 1430 nn = &nod1; 1431 } 1432 m = 0; 1433 if(nn->op != OIND) { 1434 if(nn->op == OREGPAIR) { 1435 m = 1; 1436 regsalloc(&nod1, nn); 1437 d = &nod1; 1438 }else 1439 d = nn; 1440 d = new1(OADDR, d, Z); 1441 d->type = types[TIND]; 1442 d->addable = 0; 1443 } else 1444 d = nn->left; 1445 n = new(OFUNC, l, new(OLIST, d, r)); 1446 n->complex = FNX; 1447 n->type = types[TVOID]; 1448 n->left->type = types[TVOID]; 1449 cgen(n, Z); 1450 if(m) 1451 gmove(&nod1, nn); 1452 break; 1453 1454 default: 1455 diag(n, "bad cgen64 %O", o); 1456 break; 1457 } 1458 cursafe = curs; 1459 } 1460