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