1: # 2: /* 3: 4: C compiler, part 2 5: 6: 7: */ 8: 9: #include "c1.h" 10: 11: #define dbprint(op) /* */ 12: #ifdef DEBUG 13: #define dbprint(op) printf(" / %s", opntab[op]) 14: #endif 15: 16: char maprel[] { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ, 17: LESS, GREATQP, GREATP, LESSEQP, LESSP 18: }; 19: 20: char notrel[] { NEQUAL, EQUAL, GREAT, GREATEQ, LESS, 21: LESSEQ, GREATP, GREATQP, LESSP, LESSEQP 22: }; 23: 24: struct tconst czero { CON, INT, 0}; 25: struct tconst cone { CON, INT, 1}; 26: 27: struct tname sfuncr { NAME, STRUCT, STATIC, 0, 0, 0 }; 28: 29: struct table *cregtab; 30: 31: int nreg 3; 32: int isn 10000; 33: 34: main(argc, argv) 35: char *argv[]; 36: { 37: 38: if (argc<4) { 39: error("Arg count"); 40: exit(1); 41: } 42: if (freopen(argv[1], "r", stdin)==NULL) { 43: error("Missing temp file"); 44: exit(1); 45: } 46: if ((freopen(argv[3], "w", stdout)) == NULL) { 47: error("Can't create %s", argv[3]); 48: exit(1); 49: } 50: funcbase = curbase = coremax = sbrk(0); 51: getree(); 52: /* 53: * If any floating-point instructions 54: * were used, generate a reference that 55: * pulls in the floating-point part of printf. 56: */ 57: if (nfloat) 58: printf(".globl fltused\n"); 59: /* 60: * tack on the string file. 61: */ 62: printf(".globl\n.data\n"); 63: if (*argv[2] != '-') { 64: if (freopen(argv[2], "r", stdin)==NULL) { 65: error("Missing temp file"); 66: exit(1); 67: } 68: getree(); 69: } 70: if (totspace >= (unsigned)56000) { 71: error("Warning: possibly too much data"); 72: nerror--; 73: } 74: exit(nerror!=0); 75: } 76: 77: /* 78: * Given a tree, a code table, and a 79: * count of available registers, find the code table 80: * for the appropriate operator such that the operands 81: * are of the right type and the number of registers 82: * required is not too large. 83: * Return a ptr to the table entry or 0 if none found. 84: */ 85: char * 86: match(atree, table, nrleft, nocvt) 87: struct tnode *atree; 88: struct table *table; 89: { 90: #define NOCVL 1 91: #define NOCVR 2 92: int op, d1, d2, dope; 93: struct tnode *p2; 94: register struct tnode *p1, *tree; 95: register struct optab *opt; 96: 97: if ((tree=atree)==0) 98: return(0); 99: if (table==lsptab) 100: table = sptab; 101: if ((op = tree->op)==0) 102: return(0); 103: dope = opdope[op]; 104: if ((dope&LEAF) == 0) 105: p1 = tree->tr1; 106: else 107: p1 = tree; 108: d1 = dcalc(p1, nrleft); 109: if ((dope&BINARY)!=0) { 110: p2 = tree->tr2; 111: /* 112: * If a subtree starts off with a conversion operator, 113: * try for a match with the conversion eliminated. 114: * E.g. int = double can be done without generating 115: * the converted int in a register by 116: * movf double,fr0; movfi fr0,int . 117: */ 118: if (opdope[p2->op]&CNVRT && (nocvt&NOCVR)==0 119: && (opdope[p2->tr1->op]&CNVRT)==0) { 120: tree->tr2 = p2->tr1; 121: if (opt = match(tree, table, nrleft, NOCVL)) 122: return(opt); 123: tree->tr2 = p2; 124: } else if (opdope[p1->op]&CNVRT && (nocvt&NOCVL)==0 125: && (opdope[p1->tr1->op]&CNVRT)==0) { 126: tree->tr1 = p1->tr1; 127: if (opt = match(tree, table, nrleft, NOCVR)) 128: return(opt); 129: tree->tr1 = p1; 130: } 131: d2 = dcalc(p2, nrleft); 132: } 133: for (; table->op!=op; table++) 134: if (table->op==0) 135: return(0); 136: for (opt = table->tabp; opt->tabdeg1!=0; opt++) { 137: if (d1 > (opt->tabdeg1&077) 138: || (opt->tabdeg1 >= 0100 && (p1->op != STAR))) 139: continue; 140: if (notcompat(p1, opt->tabtyp1, op)) { 141: continue; 142: } 143: if ((opdope[op]&BINARY)!=0 && p2!=0) { 144: if (d2 > (opt->tabdeg2&077) 145: || (opt->tabdeg2 >= 0100) && (p2->op != STAR) ) 146: continue; 147: if (notcompat(p2,opt->tabtyp2, 0)) 148: continue; 149: } 150: return(opt); 151: } 152: return(0); 153: } 154: 155: /* 156: * Given a tree, a code table, and a register, 157: * produce code to evaluate the tree with the appropriate table. 158: * Registers reg and upcan be used. 159: * If there is a value, it is desired that it appear in reg. 160: * The routine returns the register in which the value actually appears. 161: * This routine must work or there is an error. 162: * If the table called for is cctab, sptab, or efftab, 163: * and tree can't be done using the called-for table, 164: * another try is made. 165: * If the tree can't be compiled using cctab, regtab is 166: * used and a "tst" instruction is produced. 167: * If the tree can't be compiled using sptab, 168: * regtab is used and the register is pushed on the stack. 169: * If the tree can't be compiled using efftab, 170: * just use regtab. 171: * Regtab must succeed or an "op not found" error results. 172: * 173: * A number of special cases are recognized, and 174: * there is an interaction with the optimizer routines. 175: */ 176: rcexpr(atree, atable, reg) 177: struct tnode *atree; 178: struct table *atable; 179: { 180: register r; 181: int modf, nargs, recurf; 182: register struct tnode *tree; 183: register struct table *table; 184: 185: table = atable; 186: recurf = 0; 187: if (reg<0) { 188: recurf++; 189: reg = ~reg; 190: if (reg>=020) { 191: reg =- 020; 192: recurf++; 193: } 194: } 195: again: 196: if((tree=atree)==0) 197: return(0); 198: if (opdope[tree->op]&RELAT && tree->tr2->op==CON && tree->tr2->value==0 199: && table==cctab) 200: tree = atree = tree->tr1; 201: /* 202: * fieldselect(...) : in efftab mode, 203: * ignore the select, otherwise 204: * do the shift and mask. 205: */ 206: if (tree->op == FSELT) { 207: if (table==efftab) 208: atree = tree = tree->tr1; 209: else { 210: tree->op = FSEL; 211: atree = tree = optim(tree); 212: } 213: } 214: switch (tree->op) { 215: 216: /* 217: * Structure assignments 218: */ 219: case STRASG: 220: strasg(tree); 221: return(0); 222: 223: /* 224: * An initializing expression 225: */ 226: case INIT: 227: tree = optim(tree); 228: doinit(tree->type, tree->tr1); 229: return(0); 230: 231: /* 232: * Put the value of an expression in r0, 233: * for a switch or a return 234: */ 235: case RFORCE: 236: tree = tree->tr1; 237: if((r=rcexpr(tree, regtab, reg)) != 0) 238: movreg(r, 0, tree); 239: return(0); 240: 241: /* 242: * sequential execution 243: */ 244: case SEQNC: 245: r = nstack; 246: rcexpr(tree->tr1, efftab, reg); 247: nstack = r; 248: atree = tree = tree->tr2; 249: goto again; 250: 251: /* 252: * In the generated &~ operator, 253: * fiddle things so a PDP-11 "bit" 254: * instruction will be produced when cctab is used. 255: */ 256: case ANDN: 257: if (table==cctab) { 258: tree->op = TAND; 259: tree->tr2 = optim(tnode(COMPL, tree->type, tree->tr2)); 260: } 261: break; 262: 263: /* 264: * Handle a subroutine call. It has to be done 265: * here because if cexpr got called twice, the 266: * arguments might be compiled twice. 267: * There is also some fiddling so the 268: * first argument, in favorable circumstances, 269: * goes to (sp) instead of -(sp), reducing 270: * the amount of stack-popping. 271: */ 272: case CALL: 273: r = 0; 274: nargs = 0; 275: modf = 0; 276: if (tree->tr1->op!=NAME || tree->tr1->class!=EXTERN) { 277: nargs++; 278: nstack++; 279: } 280: tree = tree->tr2; 281: if(tree->op) { 282: while (tree->op==COMMA) { 283: r =+ comarg(tree->tr2, &modf); 284: tree = tree->tr1; 285: nargs++; 286: } 287: r =+ comarg(tree, &modf); 288: nargs++; 289: } 290: tree = atree; 291: tree->op = CALL2; 292: if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN) 293: tree->op = CALL1; 294: if (cexpr(tree, regtab, reg)<0) 295: error("compiler botch: call"); 296: popstk(r); 297: nstack =- nargs; 298: if (table==efftab || table==regtab) 299: return(0); 300: r = 0; 301: goto fixup; 302: 303: /* 304: * Longs need special treatment. 305: */ 306: case ASLSH: 307: case LSHIFT: 308: if (tree->type==LONG) { 309: if (tree->tr2->op==ITOL) 310: tree->tr2 = tree->tr2->tr1; 311: else 312: tree->tr2 = optim(tnode(LTOI,INT,tree->tr2)); 313: if (tree->op==ASLSH) 314: tree->op = ASLSHL; 315: else 316: tree->op = LLSHIFT; 317: } 318: break; 319: 320: /* 321: * Try to change * to shift. 322: */ 323: case TIMES: 324: case ASTIMES: 325: tree = pow2(tree); 326: } 327: /* 328: * Try to find postfix ++ and -- operators that can be 329: * pulled out and done after the rest of the expression 330: */ 331: if (table!=cctab && table!=cregtab && recurf<2 332: && (opdope[tree->op]&LEAF)==0) { 333: if (r=delay(&atree, table, reg)) { 334: tree = atree; 335: table = efftab; 336: reg = r-1; 337: } 338: } 339: /* 340: * Basically, try to reorder the computation 341: * so reg = x+y is done as reg = x; reg =+ y 342: */ 343: if (recurf==0 && reorder(&atree, table, reg)) { 344: if (table==cctab && atree->op==NAME) 345: return(reg); 346: } 347: tree = atree; 348: if (table==efftab && tree->op==NAME) 349: return(reg); 350: if ((r=cexpr(tree, table, reg))>=0) 351: return(r); 352: if (table!=regtab && (table!=cctab||(opdope[tree->op]&RELAT)==0)) { 353: if((r=cexpr(tree, regtab, reg))>=0) { 354: fixup: 355: modf = isfloat(tree); 356: dbprint(tree->op); 357: if (table==sptab || table==lsptab) { 358: if (tree->type==LONG) { 359: printf("mov\tr%d,-(sp)\n",r+1); 360: nstack++; 361: } 362: printf("mov%c r%d,%c(sp)\n", modf, r, 363: table==sptab? '-':0); 364: nstack++; 365: } 366: if (table==cctab) 367: printf("tst%c r%d\n", modf, r); 368: return(r); 369: } 370: } 371: /* 372: * There's a last chance for this operator 373: */ 374: if (tree->op==LTOI) { 375: r = rcexpr(tree->tr1, regtab, reg); 376: if (r >= 0) { 377: r++; 378: goto fixup; 379: } 380: } 381: if (tree->type == STRUCT) 382: error("Illegal operation on structure"); 383: else if (tree->op>0 && tree->op<RFORCE && opntab[tree->op]) 384: error("No code table for op: %s", opntab[tree->op]); 385: else 386: error("No code table for op %d", tree->op); 387: return(reg); 388: } 389: 390: /* 391: * Try to compile the tree with the code table using 392: * registers areg and up. If successful, 393: * return the register where the value actually ended up. 394: * If unsuccessful, return -1. 395: * 396: * Most of the work is the macro-expansion of the 397: * code table. 398: */ 399: cexpr(atree, table, areg) 400: struct tnode *atree; 401: struct table *table; 402: { 403: int c, r; 404: register struct tnode *p, *p1, *tree; 405: struct table *ctable; 406: struct tnode *p2; 407: char *string; 408: int reg, reg1, rreg, flag, opd; 409: char *opt; 410: 411: tree = atree; 412: reg = areg; 413: p1 = tree->tr2; 414: c = tree->op; 415: opd = opdope[c]; 416: /* 417: * When the value of a relational or a logical expression is 418: * desired, more work must be done. 419: */ 420: if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) { 421: cbranch(tree, c=isn++, 1, reg); 422: rcexpr(&czero, table, reg); 423: branch(isn, 0); 424: label(c); 425: rcexpr(&cone, table, reg); 426: label(isn++); 427: return(reg); 428: } 429: if(c==QUEST) { 430: if (table==cctab) 431: return(-1); 432: cbranch(tree->tr1, c=isn++, 0, reg); 433: flag = nstack; 434: rreg = rcexpr(p1->tr1, table, reg); 435: nstack = flag; 436: branch(r=isn++, 0); 437: label(c); 438: reg = rcexpr(p1->tr2, table, rreg); 439: if (rreg!=reg) 440: movreg(reg, rreg, tree->tr2); 441: label(r); 442: return(rreg); 443: } 444: reg = oddreg(tree, reg); 445: reg1 = reg+1; 446: /* 447: * long values take 2 registers. 448: */ 449: if ((tree->type==LONG||opd&RELAT&&tree->tr1->type==LONG) && tree->op!=ITOL) 450: reg1++; 451: /* 452: * Leaves of the expression tree 453: */ 454: if ((r = chkleaf(tree, table, reg)) >= 0) 455: return(r); 456: /* 457: * x + (-1) is better done as x-1. 458: */ 459: 460: if ((tree->op==PLUS||tree->op==ASPLUS) && 461: (p1=tree->tr2)->op == CON && p1->value == -1) { 462: p1->value = 1; 463: tree->op =+ (MINUS-PLUS); 464: } 465: /* 466: * Because of a peculiarity of the PDP11 table 467: * char = *intreg++ and *--intreg cannot go through. 468: */ 469: if (tree->tr1->type==CHAR && tree->tr2->type!=CHAR 470: && (tree->tr2->op==AUTOI||tree->tr2->op==AUTOD)) 471: tree->tr2 = tnode(LOAD, tree->tr2->type, tree->tr2); 472: if (table==cregtab) 473: table = regtab; 474: /* 475: * The following peculiar code depends on the fact that 476: * if you just want the codition codes set, efftab 477: * will generate the right code unless the operator is 478: * a shift or 479: * postfix ++ or --. Unravelled, if the table is 480: * cctab and the operator is not special, try first 481: * for efftab; if the table isn't, if the operator is, 482: * or the first match fails, try to match 483: * with the table actually asked for. 484: */ 485: /* 486: * Account for longs and oddregs; below is really 487: * r = nreg - reg - (reg-areg) - (reg1-reg-1); 488: */ 489: r = nreg - reg + areg - reg1 + 1; 490: if (table!=cctab || c==INCAFT || c==DECAFT || tree->type==LONG 491: || c==ASRSH || c==ASLSH || c==ASULSH 492: || (opt = match(tree, efftab, r, 0)) == 0) 493: if ((opt=match(tree, table, r, 0))==0) 494: return(-1); 495: string = opt->tabstring; 496: p1 = tree->tr1; 497: if (p1->op==FCON && p1->value>0) { 498: printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p1->value, p1->fvalue); 499: p1->value = -p1->value; 500: } 501: p2 = 0; 502: if (opdope[tree->op]&BINARY) { 503: p2 = tree->tr2; 504: if (p2->op==FCON && p2->value>0) { 505: printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p2->value, p2->fvalue); 506: p2->value = -p2->value; 507: } 508: } 509: loop: 510: /* 511: * The 0200 bit asks for a tab. 512: */ 513: if ((c = *string++) & 0200) { 514: c =& 0177; 515: putchar('\t'); 516: } 517: switch (c) { 518: 519: case '\n': 520: dbprint(tree->op); 521: break; 522: 523: case '\0': 524: if (!isfloat(tree)) 525: if (tree->op==DIVIDE||tree->op==ASDIV||tree->op==PTOI) 526: reg--; 527: return(reg); 528: 529: /* A1 */ 530: case 'A': 531: p = p1; 532: goto adr; 533: 534: /* A2 */ 535: case 'B': 536: p = p2; 537: goto adr; 538: 539: adr: 540: c = 0; 541: while (*string=='\'') { 542: c++; 543: string++; 544: } 545: if (*string=='+') { 546: c = 100; 547: string++; 548: } 549: pname(p, c); 550: goto loop; 551: 552: /* I */ 553: case 'M': 554: if ((c = *string)=='\'') 555: string++; 556: else 557: c = 0; 558: prins(tree->op, c, instab); 559: goto loop; 560: 561: /* B1 */ 562: case 'C': 563: if ((opd&LEAF) != 0) 564: p = tree; 565: else 566: p = p1; 567: goto pbyte; 568: 569: /* BF */ 570: case 'P': 571: p = tree; 572: goto pb1; 573: 574: /* B2 */ 575: case 'D': 576: p = p2; 577: pbyte: 578: if (p->type==CHAR) 579: putchar('b'); 580: pb1: 581: if (isfloat(p)) 582: putchar('f'); 583: goto loop; 584: 585: /* BE */ 586: case 'L': 587: if (p1->type==CHAR || p2->type==CHAR) 588: putchar('b'); 589: p = tree; 590: goto pb1; 591: 592: /* F */ 593: case 'G': 594: p = p1; 595: flag = 01; 596: goto subtre; 597: 598: /* S */ 599: case 'K': 600: p = p2; 601: flag = 02; 602: goto subtre; 603: 604: /* H */ 605: case 'H': 606: p = tree; 607: flag = 04; 608: 609: subtre: 610: ctable = regtab; 611: if (flag&04) 612: ctable = cregtab; 613: c = *string++ - 'A'; 614: if (*string=='!') { 615: string++; 616: c =| 020; /* force right register */ 617: } 618: if ((c&02)!=0) 619: ctable = sptab; 620: if ((c&04)!=0) 621: ctable = cctab; 622: if ((flag&01) && ctable==regtab && (c&01)==0 623: && (tree->op==DIVIDE||tree->op==MOD 624: || tree->op==ASDIV||tree->op==ASMOD||tree->op==ITOL)) 625: ctable = cregtab; 626: if ((c&01)!=0) { 627: p = p->tr1; 628: if(collcon(p) && ctable!=sptab) { 629: if (p->op==STAR) 630: p = p->tr1; 631: p = p->tr1; 632: } 633: } 634: if (table==lsptab && ctable==sptab) 635: ctable = lsptab; 636: if (c&010) 637: r = reg1; 638: else 639: if (opdope[p->op]&LEAF || p->degree < 2) 640: r = reg; 641: else 642: r = areg; 643: rreg = rcexpr(p, ctable, r); 644: if (ctable!=regtab && ctable!=cregtab) 645: goto loop; 646: if (c&010) { 647: if (c&020 && rreg!=reg1) 648: movreg(rreg, reg1, p); 649: else 650: reg1 = rreg; 651: } else if (rreg!=reg) 652: if ((c&020)==0 && oddreg(tree, 0)==0 && tree->type!=LONG 653: && (flag&04 654: || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077) 655: || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) { 656: reg = rreg; 657: reg1 = rreg+1; 658: } else 659: movreg(rreg, reg, p); 660: goto loop; 661: 662: /* R */ 663: case 'I': 664: r = reg; 665: if (*string=='-') { 666: string++; 667: r--; 668: } 669: goto preg; 670: 671: /* R1 */ 672: case 'J': 673: r = reg1; 674: preg: 675: if (*string=='+') { 676: string++; 677: r++; 678: } 679: if (r>nreg || r>=4 && tree->type==DOUBLE) 680: error("Register overflow: simplify expression"); 681: printf("r%d", r); 682: goto loop; 683: 684: case '-': /* check -(sp) */ 685: if (*string=='(') { 686: nstack++; 687: if (table!=lsptab) 688: putchar('-'); 689: goto loop; 690: } 691: break; 692: 693: case ')': /* check (sp)+ */ 694: putchar(')'); 695: if (*string=='+') 696: nstack--; 697: goto loop; 698: 699: /* #1 */ 700: case '#': 701: p = p1->tr1; 702: goto nmbr; 703: 704: /* #2 */ 705: case '"': 706: p = p2->tr1; 707: 708: nmbr: 709: if(collcon(p)) { 710: if (p->op==STAR) { 711: printf("*"); 712: p = p->tr1; 713: } 714: if ((p = p->tr2)->op == CON) { 715: if (p->value) 716: psoct(p->value); 717: } else if (p->op==AMPER) 718: pname(p->tr1, 0); 719: } 720: goto loop; 721: 722: /* 723: * Certain adjustments for / % and PTOI 724: */ 725: case 'T': 726: c = reg-1; 727: if (tree->op == PTOI) { 728: printf("bic r%d,r%d\nsbc r%d\n", c,c,c); 729: goto loop; 730: } 731: if (p1->type==UNSIGN || p1->type&XTYPE) { 732: printf("clr r%d\n", c); 733: goto loop; 734: } 735: if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0)) 736: printf("tst r%d\n", reg); 737: printf("sxt r%d\n", c); 738: goto loop; 739: 740: case 'V': /* adc sbc, clr, or sxt as required for longs */ 741: switch(tree->op) { 742: case PLUS: 743: case ASPLUS: 744: case INCBEF: 745: case INCAFT: 746: printf("adc"); 747: break; 748: 749: case MINUS: 750: case ASMINUS: 751: case NEG: 752: case DECBEF: 753: case DECAFT: 754: printf("sbc"); 755: break; 756: 757: case ASSIGN: 758: p = tree->tr2; 759: goto lcasev; 760: 761: case ASDIV: 762: case ASMOD: 763: case ASULSH: 764: p = tree->tr1; 765: lcasev: 766: if (p->type!=LONG) { 767: if (p->type==UNSIGN || p->type&XTYPE) 768: printf("clr"); 769: else 770: printf("sxt"); 771: goto loop; 772: } 773: default: 774: while ((c = *string++)!='\n' && c!='\0'); 775: break; 776: } 777: goto loop; 778: 779: /* 780: * Mask used in field assignments 781: */ 782: case 'Z': 783: printf("$%o", tree->mask); 784: goto loop; 785: 786: /* 787: * Relational on long values. 788: * Might bug out early. E.g., 789: * (long<0) can be determined with only 1 test. 790: */ 791: case 'X': 792: if (xlongrel(*string++ - '0')) 793: return(reg); 794: goto loop; 795: } 796: putchar(c); 797: goto loop; 798: } 799: 800: /* 801: * This routine just calls sreorder (below) 802: * on the subtrees and then on the tree itself. 803: * It returns non-zero if anything changed. 804: */ 805: reorder(treep, table, reg) 806: struct tnode **treep; 807: struct table *table; 808: { 809: register r, o; 810: register struct tnode *p; 811: 812: p = *treep; 813: o = p->op; 814: if (opdope[o]&LEAF || o==LOGOR || o==LOGAND) 815: return(0); 816: while(sreorder(&p->tr1, regtab, reg, 1)) 817: ; 818: if (opdope[o]&BINARY) 819: while(sreorder(&p->tr2, regtab, reg, 1)) 820: ; 821: r = 0; 822: if (table!=cctab) 823: while (sreorder(treep, table, reg, 0)) 824: r++; 825: *treep = optim(*treep); 826: return(r); 827: } 828: 829: /* 830: * Basically this routine carries out two kinds of optimization. 831: * First, it observes that "x + (reg = y)" where actually 832: * the = is any assignment op is better done as "reg=y; x+reg". 833: * In this case rcexpr is called to do the first part and the 834: * tree is modified so the name of the register 835: * replaces the assignment. 836: * Moreover, expressions like "reg = x+y" are best done as 837: * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!). 838: */ 839: sreorder(treep, table, reg, recurf) 840: struct tnode **treep; 841: struct table *table; 842: { 843: register struct tnode *p, *p1; 844: 845: p = *treep; 846: if (opdope[p->op]&LEAF) 847: return(0); 848: if (p->op==PLUS && recurf) 849: if (reorder(&p->tr2, table, reg)) 850: *treep = p = optim(p); 851: p1 = p->tr1; 852: if (p->op==STAR || p->op==PLUS) { 853: if (recurf && reorder(&p->tr1, table, reg)) 854: *treep = p = optim(p); 855: p1 = p->tr1; 856: } 857: if (p1->op==NAME) switch(p->op) { 858: case ASLSH: 859: case ASRSH: 860: case ASSIGN: 861: if (p1->class != REG||p1->type==CHAR||isfloat(p->tr2)) 862: return(0); 863: if (p->op==ASSIGN) switch (p->tr2->op) { 864: case TIMES: 865: if (!ispow2(p->tr2)) 866: break; 867: p->tr2 = pow2(p->tr2); 868: case PLUS: 869: case MINUS: 870: case AND: 871: case ANDN: 872: case OR: 873: case EXOR: 874: case LSHIFT: 875: case RSHIFT: 876: p1 = p->tr2->tr2; 877: if (xdcalc(p1, 16) > 12 878: || p1->op==NAME 879: &&(p1->nloc==p->tr1->nloc 880: || p1->regno==p->tr1->nloc)) 881: return(0); 882: p1 = p->tr2; 883: p->tr2 = p1->tr1; 884: if (p1->tr1->op!=NAME 885: || p1->tr1->class!=REG 886: || p1->tr1->nloc!=p->tr1->nloc) 887: rcexpr(p, efftab, reg); 888: p->tr2 = p1->tr2; 889: p->op = p1->op + ASPLUS - PLUS; 890: *treep = p; 891: return(1); 892: } 893: goto OK; 894: 895: case ASTIMES: 896: if (!ispow2(p)) 897: return(0); 898: case ASPLUS: 899: case ASMINUS: 900: case ASAND: 901: case ASANDN: 902: case ASOR: 903: case ASXOR: 904: case INCBEF: 905: case DECBEF: 906: OK: 907: if (table==cctab||table==cregtab) 908: reg =+ 020; 909: rcexpr(optim(p), efftab, ~reg); 910: *treep = p1; 911: return(1); 912: } 913: return(0); 914: } 915: 916: /* 917: * Delay handles postfix ++ and -- 918: * It observes that "x + y++" is better 919: * treated as "x + y; y++". 920: * If the operator is ++ or -- itself, 921: * it calls rcexpr to load the operand, letting 922: * the calling instance of rcexpr to do the 923: * ++ using efftab. 924: * Otherwise it uses sdelay to search for inc/dec 925: * among the operands. 926: */ 927: delay(treep, table, reg) 928: struct tnode **treep; 929: { 930: register struct tnode *p, *p1; 931: register r; 932: 933: p = *treep; 934: if ((p->op==INCAFT||p->op==DECAFT) 935: && p->tr1->op==NAME) { 936: return(1+rcexpr(p->tr1, table, reg)); 937: } 938: p1 = 0; 939: if (opdope[p->op]&BINARY) { 940: if (p->op==LOGAND || p->op==LOGOR) 941: return(0); 942: } 943: p1 = sdelay(&p->tr2); 944: if (p1==0) 945: p1 = sdelay(&p->tr1); 946: if (p1) { 947: r = rcexpr(optim(p), table, reg); 948: *treep = p1; 949: return(r+1); 950: } 951: return(0); 952: } 953: 954: sdelay(ap) 955: struct tnode **ap; 956: { 957: register struct tnode *p, *p1; 958: 959: p = *ap; 960: if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) { 961: *ap = ncopy(p->tr1); 962: return(p); 963: } 964: if (p->op==STAR || p->op==PLUS) 965: if (p1=sdelay(&p->tr1)) 966: return(p1); 967: if (p->op==PLUS) 968: return(sdelay(&p->tr2)); 969: return(0); 970: } 971: 972: /* 973: * Copy a tree node for a register variable. 974: * Used by sdelay because if *reg-- is turned 975: * into *reg; reg-- the *reg will in turn 976: * be changed to some offset class, accidentally 977: * modifying the reg--. 978: */ 979: ncopy(ap) 980: struct tname *ap; 981: { 982: register struct tname *p, *q; 983: 984: p = ap; 985: if (p->class!=REG) 986: return(p); 987: q = getblk(sizeof(*p)); 988: q->op = p->op; 989: q->type = p->type; 990: q->class = p->class; 991: q->offset = p->offset; 992: q->nloc = p->nloc; 993: return(q); 994: } 995: 996: /* 997: * If the tree can be immediately loaded into a register, 998: * produce code to do so and return success. 999: */ 1000: chkleaf(atree, table, reg) 1001: struct tnode *atree; 1002: { 1003: struct tnode lbuf; 1004: register struct tnode *tree; 1005: 1006: tree = atree; 1007: if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12) 1008: return(-1); 1009: lbuf.op = LOAD; 1010: lbuf.type = tree->type; 1011: lbuf.degree = tree->degree; 1012: lbuf.tr1 = tree; 1013: return(rcexpr(&lbuf, table, reg)); 1014: } 1015: 1016: /* 1017: * Compile a function argument. 1018: * If the stack is currently empty, put it in (sp) 1019: * rather than -(sp); this will save a pop. 1020: * Return the number of bytes pushed, 1021: * for future popping. 1022: */ 1023: comarg(atree, flagp) 1024: int *flagp; 1025: { 1026: register struct tnode *tree; 1027: register retval; 1028: int i; 1029: int size; 1030: 1031: tree = atree; 1032: if (tree->op==STRASG) { 1033: size = tree->mask; 1034: tree = tree->tr1; 1035: tree = strfunc(tree); 1036: if (size <= 2) { 1037: setype(tree, INT); 1038: goto normal; 1039: } 1040: if (size <= 4) { 1041: setype(tree, LONG); 1042: goto normal; 1043: } 1044: if (tree->op!=NAME && tree->op!=STAR) { 1045: error("Unimplemented structure assignment"); 1046: return(0); 1047: } 1048: tree = tnode(AMPER, STRUCT+PTR, tree); 1049: tree = tnode(PLUS, STRUCT+PTR, tree, tconst(size, INT)); 1050: tree = optim(tree); 1051: retval = rcexpr(tree, regtab, 0); 1052: size =>> 1; 1053: if (size <= 5) { 1054: for (i=0; i<size; i++) 1055: printf("mov -(r%d),-(sp)\n", retval); 1056: } else { 1057: if (retval!=0) 1058: printf("mov r%d,r0\n", retval); 1059: printf("mov $%o,r1\n", size); 1060: printf("L%d:mov -(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn, isn); 1061: isn++; 1062: } 1063: nstack++; 1064: return(size*2); 1065: } 1066: normal: 1067: if (nstack || isfloat(tree) || tree->type==LONG) { 1068: rcexpr(tree, sptab, 0); 1069: retval = arlength(tree->type); 1070: } else { 1071: (*flagp)++; 1072: rcexpr(tree, lsptab, 0); 1073: retval = 0; 1074: } 1075: return(retval); 1076: } 1077: 1078: struct tnode * 1079: strfunc(atp) 1080: struct tnode *atp; 1081: { 1082: register struct tnode *tp; 1083: 1084: tp = atp; 1085: if (tp->op != CALL) 1086: return(tp); 1087: setype(tp, STRUCT+PTR); 1088: return(tnode(STAR, STRUCT, tp)); 1089: } 1090: 1091: /* 1092: * Compile an initializing expression 1093: */ 1094: doinit(atype, atree) 1095: struct tnode *atree; 1096: { 1097: register struct tnode *tree; 1098: register int type; 1099: float sfval; 1100: double fval; 1101: long lval; 1102: 1103: tree = atree; 1104: type = atype; 1105: if (type==CHAR) { 1106: printf(".byte "); 1107: if (tree->type&XTYPE) 1108: goto illinit; 1109: type = INT; 1110: } 1111: if (type&XTYPE) 1112: type = INT; 1113: switch (type) { 1114: case INT: 1115: case UNSIGN: 1116: if (tree->op==FTOI) { 1117: if (tree->tr1->op!=FCON && tree->tr1->op!=SFCON) 1118: goto illinit; 1119: tree = tree->tr1; 1120: tree->value = tree->fvalue; 1121: tree->op = CON; 1122: } else if (tree->op==LTOI) { 1123: if (tree->tr1->op!=LCON) 1124: goto illinit; 1125: tree = tree->tr1; 1126: lval = tree->lvalue; 1127: tree->op = CON; 1128: tree->value = lval; 1129: } 1130: if (tree->op == CON) 1131: printf("%o\n", tree->value); 1132: else if (tree->op==AMPER) { 1133: pname(tree->tr1, 0); 1134: putchar('\n'); 1135: } else 1136: goto illinit; 1137: return; 1138: 1139: case DOUBLE: 1140: case FLOAT: 1141: if (tree->op==ITOF) { 1142: if (tree->tr1->op==CON) { 1143: fval = tree->tr1->value; 1144: } else 1145: goto illinit; 1146: } else if (tree->op==FCON || tree->op==SFCON) 1147: fval = tree->fvalue; 1148: else if (tree->op==LTOF) { 1149: if (tree->tr1->op!=LCON) 1150: goto illinit; 1151: fval = tree->tr1->lvalue; 1152: } else 1153: goto illinit; 1154: if (type==FLOAT) { 1155: sfval = fval; 1156: printf("%o; %o\n", sfval); 1157: } else 1158: printf("%o; %o; %o; %o\n", fval); 1159: return; 1160: 1161: case LONG: 1162: if (tree->op==FTOL) { 1163: tree = tree->tr1; 1164: if (tree->op==SFCON) 1165: tree->op = FCON; 1166: if (tree->op!= FCON) 1167: goto illinit; 1168: lval = tree->fvalue; 1169: } else if (tree->op==ITOL) { 1170: if (tree->tr1->op != CON) 1171: goto illinit; 1172: lval = tree->tr1->value; 1173: } else if (tree->op==LCON) 1174: lval = tree->lvalue; 1175: else 1176: goto illinit; 1177: printf("%o; %o\n", lval); 1178: return; 1179: } 1180: illinit: 1181: error("Illegal initialization"); 1182: } 1183: 1184: movreg(r0, r1, tree) 1185: struct tnode *tree; 1186: { 1187: register char *s; 1188: 1189: if (r0==r1) 1190: return; 1191: if (tree->type==LONG) { 1192: s = "mov r%d,r%d\nmov r%d,r%d\n"; 1193: if (r0 < r1) 1194: printf(s, r0+1,r1+1,r0,r1); 1195: else 1196: printf(s, r0,r1,r0+1,r1+1); 1197: return; 1198: } 1199: printf("mov%c r%d,r%d\n", isfloat(tree), r0, r1); 1200: }