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