1 #include "gc.h" 2 3 void 4 codgen(Node *n, Node *nn) 5 { 6 Prog *sp; 7 Node *n1, nod, nod1; 8 9 cursafe = 0; 10 curarg = 0; 11 maxargsafe = 0; 12 13 /* 14 * isolate name 15 */ 16 for(n1 = nn;; n1 = n1->left) { 17 if(n1 == Z) { 18 diag(nn, "cant find function name"); 19 return; 20 } 21 if(n1->op == ONAME) 22 break; 23 } 24 nearln = nn->lineno; 25 gpseudo(ATEXT, n1->sym, nodconst(stkoff)); 26 27 /* 28 * isolate first argument 29 */ 30 if(REGARG) { 31 if(typesuv[thisfn->link->etype]) { 32 nod1 = *nodret->left; 33 nodreg(&nod, &nod1, REGARG); 34 gmove(&nod, &nod1); 35 } else 36 if(firstarg && typechlp[firstargtype->etype]) { 37 nod1 = *nodret->left; 38 nod1.sym = firstarg; 39 nod1.type = firstargtype; 40 nod1.xoffset = align(0, firstargtype, Aarg1); 41 nod1.etype = firstargtype->etype; 42 nodreg(&nod, &nod1, REGARG); 43 gmove(&nod, &nod1); 44 } 45 } 46 47 sp = p; 48 retok = 0; 49 gen(n); 50 if(!retok) 51 if(thisfn->link->etype != TVOID) 52 warn(Z, "no return at end of function: %s", n1->sym->name); 53 noretval(3); 54 if(thisfn && thisfn->link && typefd[thisfn->link->etype]) 55 gins(AFLDZ, Z, Z); 56 gbranch(ORETURN); 57 58 if(!debug['N'] || debug['R'] || debug['P']) 59 regopt(sp); 60 sp->to.offset += maxargsafe; 61 } 62 63 void 64 supgen(Node *n) 65 { 66 long spc; 67 Prog *sp; 68 69 if(n == Z) 70 return; 71 suppress++; 72 spc = pc; 73 sp = lastp; 74 gen(n); 75 lastp = sp; 76 pc = spc; 77 sp->link = nil; 78 suppress--; 79 } 80 81 void 82 gen(Node *n) 83 { 84 Node *l, nod; 85 Prog *sp, *spc, *spb; 86 Case *cn; 87 long sbc, scc; 88 int f, o; 89 90 loop: 91 if(n == Z) 92 return; 93 nearln = n->lineno; 94 o = n->op; 95 if(debug['G']) 96 if(o != OLIST) 97 print("%L %O\n", nearln, o); 98 99 retok = 0; 100 switch(o) { 101 102 default: 103 complex(n); 104 cgen(n, Z); 105 break; 106 107 case OLIST: 108 gen(n->left); 109 110 rloop: 111 n = n->right; 112 goto loop; 113 114 case ORETURN: 115 retok = 1; 116 complex(n); 117 if(n->type == T) 118 break; 119 l = n->left; 120 if(l == Z) { 121 noretval(3); 122 if(typefd[n->type->etype]) 123 gins(AFLDZ, Z, Z); 124 gbranch(ORETURN); 125 break; 126 } 127 if(typesuv[n->type->etype]) { 128 sugen(l, nodret, n->type->width); 129 noretval(3); 130 gbranch(ORETURN); 131 break; 132 } 133 regret(&nod, n); 134 cgen(l, &nod); 135 regfree(&nod); 136 if(typefd[n->type->etype]) 137 noretval(1); 138 else 139 noretval(2); 140 gbranch(ORETURN); 141 break; 142 143 case OLABEL: 144 l = n->left; 145 if(l) { 146 l->xoffset = pc; 147 if(l->label) 148 patch(l->label, pc); 149 } 150 gbranch(OGOTO); /* prevent self reference in reg */ 151 patch(p, pc); 152 goto rloop; 153 154 case OGOTO: 155 retok = 1; 156 n = n->left; 157 if(n == Z) 158 return; 159 if(n->complex == 0) { 160 diag(Z, "label undefined: %s", n->sym->name); 161 return; 162 } 163 if(suppress) 164 return; 165 gbranch(OGOTO); 166 if(n->xoffset) { 167 patch(p, n->xoffset); 168 return; 169 } 170 if(n->label) 171 patch(n->label, pc-1); 172 n->label = p; 173 return; 174 175 case OCASE: 176 l = n->left; 177 if(cases == C) 178 diag(n, "case/default outside a switch"); 179 if(l == Z) { 180 cas(); 181 cases->val = 0; 182 cases->def = 1; 183 cases->label = pc; 184 goto rloop; 185 } 186 complex(l); 187 if(l->type == T) 188 goto rloop; 189 if(l->op == OCONST) 190 if(typechl[l->type->etype]) { 191 cas(); 192 cases->val = l->vconst; 193 cases->def = 0; 194 cases->label = pc; 195 goto rloop; 196 } 197 diag(n, "case expression must be integer constant"); 198 goto rloop; 199 200 case OSWITCH: 201 l = n->left; 202 complex(l); 203 if(l->type == T) 204 break; 205 if(!typechl[l->type->etype]) { 206 diag(n, "switch expression must be integer"); 207 break; 208 } 209 210 gbranch(OGOTO); /* entry */ 211 sp = p; 212 213 cn = cases; 214 cases = C; 215 cas(); 216 217 sbc = breakpc; 218 breakpc = pc; 219 gbranch(OGOTO); 220 spb = p; 221 222 gen(n->right); 223 gbranch(OGOTO); 224 patch(p, breakpc); 225 226 patch(sp, pc); 227 regalloc(&nod, l, Z); 228 nod.type = types[TLONG]; 229 cgen(l, &nod); 230 doswit(&nod); 231 regfree(&nod); 232 patch(spb, pc); 233 234 cases = cn; 235 breakpc = sbc; 236 break; 237 238 case OWHILE: 239 case ODWHILE: 240 l = n->left; 241 gbranch(OGOTO); /* entry */ 242 sp = p; 243 244 scc = continpc; 245 continpc = pc; 246 gbranch(OGOTO); 247 spc = p; 248 249 sbc = breakpc; 250 breakpc = pc; 251 gbranch(OGOTO); 252 spb = p; 253 254 patch(spc, pc); 255 if(n->op == OWHILE) 256 patch(sp, pc); 257 bcomplex(l, Z); /* test */ 258 patch(p, breakpc); 259 260 if(n->op == ODWHILE) 261 patch(sp, pc); 262 gen(n->right); /* body */ 263 gbranch(OGOTO); 264 patch(p, continpc); 265 266 patch(spb, pc); 267 continpc = scc; 268 breakpc = sbc; 269 break; 270 271 case OFOR: 272 l = n->left; 273 gen(l->right->left); /* init */ 274 gbranch(OGOTO); /* entry */ 275 sp = p; 276 277 scc = continpc; 278 continpc = pc; 279 gbranch(OGOTO); 280 spc = p; 281 282 sbc = breakpc; 283 breakpc = pc; 284 gbranch(OGOTO); 285 spb = p; 286 287 patch(spc, pc); 288 gen(l->right->right); /* inc */ 289 patch(sp, pc); 290 if(l->left != Z) { /* test */ 291 bcomplex(l->left, Z); 292 patch(p, breakpc); 293 } 294 gen(n->right); /* body */ 295 gbranch(OGOTO); 296 patch(p, continpc); 297 298 patch(spb, pc); 299 continpc = scc; 300 breakpc = sbc; 301 break; 302 303 case OCONTINUE: 304 if(continpc < 0) { 305 diag(n, "continue not in a loop"); 306 break; 307 } 308 gbranch(OGOTO); 309 patch(p, continpc); 310 break; 311 312 case OBREAK: 313 if(breakpc < 0) { 314 diag(n, "break not in a loop"); 315 break; 316 } 317 gbranch(OGOTO); 318 patch(p, breakpc); 319 break; 320 321 case OIF: 322 l = n->left; 323 if(bcomplex(l, n->right)) { 324 if(typefd[l->type->etype]) 325 f = !l->fconst; 326 else 327 f = !l->vconst; 328 if(debug['c']) 329 print("%L const if %s\n", nearln, f ? "false" : "true"); 330 if(f) { 331 supgen(n->right->left); 332 gen(n->right->right); 333 } 334 else { 335 gen(n->right->left); 336 supgen(n->right->right); 337 } 338 } 339 else { 340 sp = p; 341 if(n->right->left != Z) 342 gen(n->right->left); 343 if(n->right->right != Z) { 344 gbranch(OGOTO); 345 patch(sp, pc); 346 sp = p; 347 gen(n->right->right); 348 } 349 patch(sp, pc); 350 } 351 break; 352 353 case OSET: 354 case OUSED: 355 usedset(n->left, o); 356 break; 357 } 358 } 359 360 void 361 usedset(Node *n, int o) 362 { 363 if(n->op == OLIST) { 364 usedset(n->left, o); 365 usedset(n->right, o); 366 return; 367 } 368 complex(n); 369 switch(n->op) { 370 case OADDR: /* volatile */ 371 gins(ANOP, n, Z); 372 break; 373 case ONAME: 374 if(o == OSET) 375 gins(ANOP, Z, n); 376 else 377 gins(ANOP, n, Z); 378 break; 379 } 380 } 381 382 void 383 noretval(int n) 384 { 385 386 if(n & 1) { 387 gins(ANOP, Z, Z); 388 p->to.type = REGRET; 389 } 390 if(n & 2) { 391 gins(ANOP, Z, Z); 392 p->to.type = FREGRET; 393 } 394 } 395 396 /* welcome to commute */ 397 static void 398 commute(Node *n) 399 { 400 Node *l, *r; 401 402 l = n->left; 403 r = n->right; 404 if(r->complex > l->complex) { 405 n->left = r; 406 n->right = l; 407 } 408 } 409 410 void 411 indexshift(Node *n) 412 { 413 int g; 414 415 if(!typechlp[n->type->etype]) 416 return; 417 simplifyshift(n); 418 if(n->op == OASHL && n->right->op == OCONST){ 419 g = vconst(n->right); 420 if(g >= 0 && g < 4) 421 n->addable = 7; 422 } 423 } 424 425 /* 426 * calculate addressability as follows 427 * NAME ==> 10/11 name+value(SB/SP) 428 * REGISTER ==> 12 register 429 * CONST ==> 20 $value 430 * *(20) ==> 21 value 431 * &(10) ==> 13 $name+value(SB) 432 * &(11) ==> 1 $name+value(SP) 433 * (13) + (20) ==> 13 fold constants 434 * (1) + (20) ==> 1 fold constants 435 * *(13) ==> 10 back to name 436 * *(1) ==> 11 back to name 437 * 438 * (20) * (X) ==> 7 multiplier in indexing 439 * (X,7) + (13,1) ==> 8 adder in indexing (addresses) 440 * (8) ==> &9(OINDEX) index, almost addressable 441 * 442 * calculate complexity (number of registers) 443 */ 444 void 445 xcom(Node *n) 446 { 447 Node *l, *r; 448 int g; 449 450 if(n == Z) 451 return; 452 l = n->left; 453 r = n->right; 454 n->complex = 0; 455 n->addable = 0; 456 switch(n->op) { 457 case OCONST: 458 n->addable = 20; 459 break; 460 461 case ONAME: 462 n->addable = 10; 463 if(n->class == CPARAM || n->class == CAUTO) 464 n->addable = 11; 465 break; 466 467 case OREGISTER: 468 n->addable = 12; 469 break; 470 471 case OINDREG: 472 n->addable = 12; 473 break; 474 475 case OADDR: 476 xcom(l); 477 if(l->addable == 10) 478 n->addable = 13; 479 else 480 if(l->addable == 11) 481 n->addable = 1; 482 break; 483 484 case OADD: 485 xcom(l); 486 xcom(r); 487 if(n->type->etype != TIND) 488 break; 489 490 switch(r->addable) { 491 case 20: 492 switch(l->addable) { 493 case 1: 494 case 13: 495 commadd: 496 l->type = n->type; 497 *n = *l; 498 l = new(0, Z, Z); 499 *l = *(n->left); 500 l->xoffset += r->vconst; 501 n->left = l; 502 r = n->right; 503 goto brk; 504 } 505 break; 506 507 case 1: 508 case 13: 509 case 10: 510 case 11: 511 /* l is the base, r is the index */ 512 if(l->addable != 20) 513 n->addable = 8; 514 break; 515 } 516 switch(l->addable) { 517 case 20: 518 switch(r->addable) { 519 case 13: 520 case 1: 521 r = n->left; 522 l = n->right; 523 n->left = l; 524 n->right = r; 525 goto commadd; 526 } 527 break; 528 529 case 13: 530 case 1: 531 case 10: 532 case 11: 533 /* r is the base, l is the index */ 534 if(r->addable != 20) 535 n->addable = 8; 536 break; 537 } 538 if(n->addable == 8 && !side(n)) { 539 indx(n); 540 l = new1(OINDEX, idx.basetree, idx.regtree); 541 l->scale = idx.scale; 542 l->addable = 9; 543 l->complex = l->right->complex; 544 l->type = l->left->type; 545 n->op = OADDR; 546 n->left = l; 547 n->right = Z; 548 n->addable = 8; 549 break; 550 } 551 break; 552 553 case OINDEX: 554 xcom(l); 555 xcom(r); 556 n->addable = 9; 557 break; 558 559 case OIND: 560 xcom(l); 561 if(l->op == OADDR) { 562 l = l->left; 563 l->type = n->type; 564 *n = *l; 565 return; 566 } 567 switch(l->addable) { 568 case 20: 569 n->addable = 21; 570 break; 571 case 1: 572 n->addable = 11; 573 break; 574 case 13: 575 n->addable = 10; 576 break; 577 } 578 break; 579 580 case OASHL: 581 xcom(l); 582 xcom(r); 583 indexshift(n); 584 break; 585 586 case OMUL: 587 case OLMUL: 588 xcom(l); 589 xcom(r); 590 g = vlog(l); 591 if(g >= 0) { 592 n->left = r; 593 n->right = l; 594 l = r; 595 r = n->right; 596 } 597 g = vlog(r); 598 if(g >= 0) { 599 n->op = OASHL; 600 r->vconst = g; 601 r->type = types[TINT]; 602 indexshift(n); 603 break; 604 } 605 commute(n); 606 break; 607 608 case OASLDIV: 609 xcom(l); 610 xcom(r); 611 g = vlog(r); 612 if(g >= 0) { 613 n->op = OASLSHR; 614 r->vconst = g; 615 r->type = types[TINT]; 616 } 617 break; 618 619 case OLDIV: 620 xcom(l); 621 xcom(r); 622 g = vlog(r); 623 if(g >= 0) { 624 n->op = OLSHR; 625 r->vconst = g; 626 r->type = types[TINT]; 627 indexshift(n); 628 break; 629 } 630 break; 631 632 case OASLMOD: 633 xcom(l); 634 xcom(r); 635 g = vlog(r); 636 if(g >= 0) { 637 n->op = OASAND; 638 r->vconst--; 639 } 640 break; 641 642 case OLMOD: 643 xcom(l); 644 xcom(r); 645 g = vlog(r); 646 if(g >= 0) { 647 n->op = OAND; 648 r->vconst--; 649 } 650 break; 651 652 case OASMUL: 653 case OASLMUL: 654 xcom(l); 655 xcom(r); 656 g = vlog(r); 657 if(g >= 0) { 658 n->op = OASASHL; 659 r->vconst = g; 660 } 661 break; 662 663 case OLSHR: 664 case OASHR: 665 xcom(l); 666 xcom(r); 667 indexshift(n); 668 break; 669 670 default: 671 if(l != Z) 672 xcom(l); 673 if(r != Z) 674 xcom(r); 675 break; 676 } 677 brk: 678 if(n->addable >= 10) 679 return; 680 if(l != Z) 681 n->complex = l->complex; 682 if(r != Z) { 683 if(r->complex == n->complex) 684 n->complex = r->complex+1; 685 else 686 if(r->complex > n->complex) 687 n->complex = r->complex; 688 } 689 if(n->complex == 0) 690 n->complex++; 691 692 if(com64(n)) 693 return; 694 695 switch(n->op) { 696 697 case OFUNC: 698 n->complex = FNX; 699 break; 700 701 case OLMOD: 702 case OMOD: 703 case OLMUL: 704 case OLDIV: 705 case OMUL: 706 case ODIV: 707 case OASLMUL: 708 case OASLDIV: 709 case OASLMOD: 710 case OASMUL: 711 case OASDIV: 712 case OASMOD: 713 if(r->complex >= l->complex) { 714 n->complex = l->complex + 3; 715 if(r->complex > n->complex) 716 n->complex = r->complex; 717 } else { 718 n->complex = r->complex + 3; 719 if(l->complex > n->complex) 720 n->complex = l->complex; 721 } 722 break; 723 724 case OLSHR: 725 case OASHL: 726 case OASHR: 727 case OASLSHR: 728 case OASASHL: 729 case OASASHR: 730 if(r->complex >= l->complex) { 731 n->complex = l->complex + 2; 732 if(r->complex > n->complex) 733 n->complex = r->complex; 734 } else { 735 n->complex = r->complex + 2; 736 if(l->complex > n->complex) 737 n->complex = l->complex; 738 } 739 break; 740 741 case OADD: 742 case OXOR: 743 case OAND: 744 case OOR: 745 /* 746 * immediate operators, make const on right 747 */ 748 if(l->op == OCONST) { 749 n->left = r; 750 n->right = l; 751 } 752 break; 753 754 case OEQ: 755 case ONE: 756 case OLE: 757 case OLT: 758 case OGE: 759 case OGT: 760 case OHI: 761 case OHS: 762 case OLO: 763 case OLS: 764 /* 765 * compare operators, make const on left 766 */ 767 if(r->op == OCONST) { 768 n->left = r; 769 n->right = l; 770 n->op = invrel[relindex(n->op)]; 771 } 772 break; 773 } 774 } 775 776 void 777 indx(Node *n) 778 { 779 Node *l, *r; 780 781 if(debug['x']) 782 prtree(n, "indx"); 783 784 l = n->left; 785 r = n->right; 786 if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) { 787 n->right = l; 788 n->left = r; 789 l = r; 790 r = n->right; 791 } 792 if(l->addable != 7) { 793 idx.regtree = l; 794 idx.scale = 1; 795 } else 796 if(l->right->addable == 20) { 797 idx.regtree = l->left; 798 idx.scale = 1 << l->right->vconst; 799 } else 800 if(l->left->addable == 20) { 801 idx.regtree = l->right; 802 idx.scale = 1 << l->left->vconst; 803 } else 804 diag(n, "bad index"); 805 806 idx.basetree = r; 807 if(debug['x']) { 808 print("scale = %d\n", idx.scale); 809 prtree(idx.regtree, "index"); 810 prtree(idx.basetree, "base"); 811 } 812 } 813 814 int 815 bcomplex(Node *n, Node *c) 816 { 817 Node *b, nod; 818 819 complex(n); 820 if(n->type != T) 821 if(tcompat(n, T, n->type, tnot)) 822 n->type = T; 823 if(n->type != T) { 824 if(c != Z && n->op == OCONST && deadheads(c)) 825 return 1; 826 if(typev[n->type->etype] && machcap(Z)) { 827 b = &nod; 828 b->op = ONE; 829 b->left = n; 830 b->right = new(0, Z, Z); 831 *b->right = *nodconst(0); 832 b->right->type = n->type; 833 b->type = types[TLONG]; 834 cgen64(b, Z); 835 return 0; 836 } 837 bool64(n); 838 boolgen(n, 1, Z); 839 } else 840 gbranch(OGOTO); 841 return 0; 842 } 843