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