1: # 2: /* 3: * C compiler 4: */ 5: 6: #include "c1h.c" 7: 8: max(a, b) 9: { 10: if (a>b) 11: return(a); 12: return(b); 13: } 14: 15: degree(at) 16: struct tnode *at; 17: { 18: register struct tnode *t, *t1; 19: 20: if ((t=at)==0 || t->op==0) 21: return(0); 22: if (t->op == CON) 23: return(-3); 24: if (t->op == AMPER) 25: return(-2); 26: if (t->op==ITOL && (t1 = isconstant(t)) && t1->value>= 0) 27: return(-2); 28: if ((opdope[t->op] & LEAF) != 0) { 29: if (t->type==CHAR || t->type==FLOAT) 30: return(1); 31: return(0); 32: } 33: return(t->degree); 34: } 35: 36: pname(ap, flag) 37: struct tnode *ap; 38: { 39: register i; 40: register struct tnode *p; 41: 42: p = ap; 43: loop: 44: switch(p->op) { 45: 46: case SFCON: 47: case CON: 48: printf("$"); 49: psoct(p->value); 50: return; 51: 52: case FCON: 53: printf("L%d", p->value); 54: return; 55: 56: case NAME: 57: i = p->offset; 58: if (flag==2) 59: i =+ 2; 60: if (i) { 61: psoct(i); 62: if (p->class!=OFFS) 63: putchar('+'); 64: if (p->class==REG) 65: regerr(); 66: } 67: switch(p->class) { 68: 69: case SOFFS: 70: case XOFFS: 71: pbase(p); 72: 73: case OFFS: 74: printf("(r%d)", p->regno); 75: return; 76: 77: case EXTERN: 78: case STATIC: 79: pbase(p); 80: return; 81: 82: case REG: 83: printf("r%d", p->nloc); 84: return; 85: 86: } 87: error("Compiler error: pname"); 88: return; 89: 90: case AMPER: 91: putchar('$'); 92: p = p->tr1; 93: if (p->op==NAME && p->class==REG) 94: regerr(); 95: goto loop; 96: 97: case AUTOI: 98: printf("(r%d)%c", p->nloc, flag==1?0:'+'); 99: return; 100: 101: case AUTOD: 102: printf("%c(r%d)", flag==1?0:'-', p->nloc); 103: return; 104: 105: case STAR: 106: p = p->tr1; 107: putchar('*'); 108: goto loop; 109: 110: } 111: error("pname called illegally"); 112: } 113: 114: regerr() 115: { 116: error("Illegal use of register"); 117: } 118: 119: pbase(ap) 120: struct tnode *ap; 121: { 122: register struct tnode *p; 123: 124: p = ap; 125: if (p->class==SOFFS || p->class==STATIC) 126: printf("L%d", p->nloc); 127: else 128: printf("_%.8s", &(p->nloc)); 129: } 130: 131: xdcalc(ap, nrleft) 132: struct tnode *ap; 133: { 134: register struct tnode *p; 135: register d; 136: 137: p = ap; 138: d = dcalc(p, nrleft); 139: if (d<20 && p->type==CHAR) { 140: if (nrleft>=1) 141: d = 20; 142: else 143: d = 24; 144: } 145: return(d); 146: } 147: 148: dcalc(ap, nrleft) 149: struct tnode *ap; 150: { 151: register struct tnode *p, *p1; 152: 153: if ((p=ap)==0) 154: return(0); 155: switch (p->op) { 156: 157: case NAME: 158: if (p->class==REG) 159: return(9); 160: 161: case AMPER: 162: case FCON: 163: case AUTOI: 164: case AUTOD: 165: return(12); 166: 167: case CON: 168: case SFCON: 169: if (p->value==0) 170: return(4); 171: if (p->value==1) 172: return(5); 173: if (p->value > 0) 174: return(8); 175: return(12); 176: 177: case STAR: 178: p1 = p->tr1; 179: if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD) 180: if (p->type!=LONG) 181: return(12); 182: } 183: if (p->type==LONG) 184: nrleft--; 185: return(p->degree <= nrleft? 20: 24); 186: } 187: 188: notcompat(ap, ast, op) 189: struct tnode *ap; 190: { 191: register at, st; 192: register struct tnode *p; 193: 194: p = ap; 195: at = p->type; 196: st = ast; 197: if (st==0) /* word, byte */ 198: return(at>CHAR && at<PTR); 199: if (st==1) /* word */ 200: return(at>INT && at<PTR); 201: st =- 2; 202: if ((at&(~(TYPE+XTYPE))) != 0) 203: at = 020; 204: if ((at&(~TYPE)) != 0) 205: at = at&TYPE | 020; 206: if (st==FLOAT && at==DOUBLE) 207: at = FLOAT; 208: if (p->op==NAME && p->class==REG && op==ASSIGN && st==CHAR) 209: return(0); 210: return(st != at); 211: } 212: 213: prins(op, c, itable) 214: struct instab *itable; 215: { 216: register struct instab *insp; 217: register char *ip; 218: 219: for (insp=itable; insp->op != 0; insp++) { 220: if (insp->op == op) { 221: ip = c? insp->str2: insp->str1; 222: if (ip==0) 223: break; 224: printf("%s", ip); 225: return; 226: } 227: } 228: error("No match' for op %d", op); 229: } 230: 231: collcon(ap) 232: struct tnode *ap; 233: { 234: register op; 235: register struct tnode *p; 236: 237: p = ap; 238: if (p->op==STAR) 239: p = p->tr1; 240: if (p->op==PLUS) { 241: op = p->tr2->op; 242: if (op==CON || op==AMPER) 243: return(1); 244: } 245: return(0); 246: } 247: 248: isfloat(at) 249: struct tnode *at; 250: { 251: register struct tnode *t; 252: 253: t = at; 254: if ((opdope[t->op]&RELAT)!=0) 255: t = t->tr1; 256: if (t->type==FLOAT || t->type==DOUBLE) { 257: nfloat = 1; 258: return('f'); 259: } 260: return(0); 261: } 262: 263: oddreg(t, areg) 264: struct tnode *t; 265: { 266: register reg; 267: 268: reg = areg; 269: if (!isfloat(t)) 270: switch(t->op) { 271: case DIVIDE: 272: case MOD: 273: case ASDIV: 274: case ASMOD: 275: reg++; 276: 277: case TIMES: 278: case ASTIMES: 279: return(reg|1); 280: } 281: return(reg); 282: } 283: 284: arlength(t) 285: { 286: if (t>=PTR) 287: return(2); 288: switch(t) { 289: 290: case INT: 291: case CHAR: 292: return(2); 293: 294: case LONG: 295: return(4); 296: 297: case FLOAT: 298: case DOUBLE: 299: return(8); 300: } 301: return(1024); 302: } 303: 304: /* 305: * Strings for switch code. 306: */ 307: 308: char dirsw[] {"\ 309: cmp r0,$%o\n\ 310: jhi L%d\n\ 311: asl r0\n\ 312: jmp *L%d(r0)\n\ 313: .data\n\ 314: L%d:\ 315: " }; 316: 317: char simpsw[] {"\ 318: mov $L%d,r1\n\ 319: mov r0,L%d\n\ 320: L%d:cmp r0,(r1)+\n\ 321: jne L%d\n\ 322: jmp *L%d-L%d(r1)\n\ 323: .data\n\ 324: L%d:\ 325: "}; 326: 327: char hashsw[] {"\ 328: mov r0,r1\n\ 329: clr r0\n\ 330: div $%o,r0\n\ 331: asl r1\n\ 332: add $L%d,r1\n\ 333: mov r0,*(r1)+\n\ 334: mov (r1)+,r1\n\ 335: L%d:cmp r0,-(r1)\n\ 336: jne L%d\n\ 337: jmp *L%d-L%d(r1)\n\ 338: .data\n\ 339: L%d:\ 340: "}; 341: 342: pswitch(afp, alp, deflab) 343: struct swtab *afp, *alp; 344: { 345: int tlab, ncase, i, j, tabs, worst, best, range; 346: register struct swtab *swp, *fp, *lp; 347: int poctab[swsiz]; 348: 349: fp = afp; 350: lp = alp; 351: if (fp==lp) { 352: printf("jbr L%d\n", deflab); 353: return; 354: } 355: tlab = isn++; 356: if (sort(fp, lp)) 357: return; 358: ncase = lp-fp; 359: lp--; 360: range = lp->swval - fp->swval; 361: /* direct switch */ 362: if (range>0 && range <= 3*ncase) { 363: if (fp->swval) 364: printf("sub $%o,r0\n", fp->swval); 365: printf(dirsw, range, deflab, isn, isn); 366: isn++; 367: for (i=fp->swval; i<=lp->swval; i++) { 368: if (i==fp->swval) { 369: printf("L%d\n", fp->swlab); 370: fp++; 371: } else 372: printf("L%d\n", deflab); 373: } 374: goto esw; 375: } 376: /* simple switch */ 377: if (ncase<8) { 378: i = isn++; 379: j = isn++; 380: printf(simpsw, i, j, isn, isn, j, i, i); 381: isn++; 382: for (; fp<=lp; fp++) 383: printf("%o\n", fp->swval); 384: printf("L%d:..\n", j); 385: for (fp = afp; fp<=lp; fp++) 386: printf("L%d\n", fp->swlab); 387: printf("L%d\n", deflab); 388: goto esw; 389: } 390: /* hash switch */ 391: best = 077777; 392: for (i=ncase/4; i<=ncase/2; i++) { 393: for (j=0; j<i; j++) 394: poctab[j] = 0; 395: for (swp=fp; swp<=lp; swp++) 396: poctab[lrem(0, swp->swval, i)]++; 397: worst = 0; 398: for (j=0; j<i; j++) 399: if (poctab[j]>worst) 400: worst = poctab[j]; 401: if (i*worst < best) { 402: tabs = i; 403: best = i*worst; 404: } 405: } 406: i = isn++; 407: printf(hashsw, tabs, isn, i, i, isn+tabs+1, isn+1, isn); 408: isn++; 409: for (i=0; i<=tabs; i++) 410: printf("L%d\n", isn+i); 411: for (i=0; i<tabs; i++) { 412: printf("L%d:..\n", isn++); 413: for (swp=fp; swp<=lp; swp++) 414: if (lrem(0, swp->swval, tabs) == i) 415: printf("%o\n", ldiv(0, swp->swval, tabs)); 416: } 417: printf("L%d:", isn++); 418: for (i=0; i<tabs; i++) { 419: printf("L%d\n", deflab); 420: for (swp=fp; swp<=lp; swp++) 421: if (lrem(0, swp->swval, tabs) == i) 422: printf("L%d\n", swp->swlab); 423: } 424: esw: 425: printf(".text\n"); 426: } 427: 428: sort(afp, alp) 429: struct swtab *afp, *alp; 430: { 431: register struct swtab *cp, *fp, *lp; 432: int intch, t; 433: 434: fp = afp; 435: lp = alp; 436: while (fp < --lp) { 437: intch = 0; 438: for (cp=fp; cp<lp; cp++) { 439: if (cp->swval == cp[1].swval) { 440: error("Duplicate case (%d)", cp->swval); 441: return(1); 442: } 443: if (cp->swval > cp[1].swval) { 444: intch++; 445: t = cp->swval; 446: cp->swval = cp[1].swval; 447: cp[1].swval = t; 448: t = cp->swlab; 449: cp->swlab = cp[1].swlab; 450: cp[1].swlab = t; 451: } 452: } 453: if (intch==0) 454: break; 455: } 456: return(0); 457: } 458: 459: ispow2(atree) 460: { 461: register int d; 462: register struct tnode *tree; 463: 464: tree = atree; 465: if (!isfloat(tree) && tree->tr2->op==CON) { 466: d = tree->tr2->value; 467: if (d>1 && (d&(d-1))==0) 468: return(d); 469: } 470: return(0); 471: } 472: 473: pow2(atree) 474: struct tnode *atree; 475: { 476: register int d, i; 477: register struct tnode *tree; 478: 479: tree = atree; 480: if (d = ispow2(tree)) { 481: for (i=0; (d=>>1)!=0; i++); 482: tree->tr2->value = i; 483: d = tree->op; 484: tree->op = d==TIMES? LSHIFT: 485: (d==DIVIDE? RSHIFT: 486: (d==ASTIMES? ASLSH: ASRSH)); 487: tree = optim(tree); 488: } 489: return(tree); 490: } 491: 492: cbranch(atree, albl, cond, areg) 493: struct tnode *atree; 494: { 495: int l1, op; 496: register lbl, reg; 497: register struct tnode *tree; 498: 499: lbl = albl; 500: reg = areg; 501: if ((tree=atree)==0) 502: return; 503: switch(tree->op) { 504: 505: case LOGAND: 506: if (cond) { 507: cbranch(tree->tr1, l1=isn++, 0, reg); 508: cbranch(tree->tr2, lbl, 1, reg); 509: label(l1); 510: } else { 511: cbranch(tree->tr1, lbl, 0, reg); 512: cbranch(tree->tr2, lbl, 0, reg); 513: } 514: return; 515: 516: case LOGOR: 517: if (cond) { 518: cbranch(tree->tr1, lbl, 1, reg); 519: cbranch(tree->tr2, lbl, 1, reg); 520: } else { 521: cbranch(tree->tr1, l1=isn++, 1, reg); 522: cbranch(tree->tr2, lbl, 0, reg); 523: label(l1); 524: } 525: return; 526: 527: case EXCLA: 528: cbranch(tree->tr1, lbl, !cond, reg); 529: return; 530: 531: case COMMA: 532: rcexpr(tree->tr1, efftab, reg); 533: tree = tree->tr2; 534: break; 535: } 536: op = tree->op; 537: if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) { 538: if (tree->type!=LONG) { 539: tree->op = MINUS; 540: tree->type = LONG; 541: tree = optim(tree); 542: } else 543: op = NEQUAL; 544: rcexpr(tree, regtab, 0); 545: printf("ashc $0,r0\n"); 546: branch(lbl, op, !cond); 547: return; 548: } 549: rcexpr(tree, cctab, reg); 550: op = tree->op; 551: if ((opdope[op]&RELAT)==0) 552: op = NEQUAL; 553: else { 554: l1 = tree->tr2->op; 555: if ((l1==CON || l1==SFCON) && tree->tr2->value==0) 556: op =+ 200; /* special for ptr tests */ 557: else 558: op = maprel[op-EQUAL]; 559: } 560: if (isfloat(tree)) 561: printf("cfcc\n"); 562: branch(lbl, op, !cond); 563: } 564: 565: branch(lbl, aop, c) 566: { 567: register op; 568: 569: if(op=aop) 570: prins(op, c, branchtab); 571: else 572: printf("jbr"); 573: printf("\tL%d\n", lbl); 574: } 575: 576: label(l) 577: { 578: printf("L%d:", l); 579: } 580: 581: popstk(a) 582: { 583: switch(a) { 584: 585: case 0: 586: return; 587: 588: case 2: 589: printf("tst (sp)+\n"); 590: return; 591: 592: case 4: 593: printf("cmp (sp)+,(sp)+\n"); 594: return; 595: } 596: printf("add $%o,sp\n", a); 597: } 598: 599: error(s, p1, p2, p3, p4, p5, p6) 600: { 601: register f; 602: extern fout; 603: 604: nerror++; 605: flush(); 606: f = fout; 607: fout = 1; 608: printf("%d: ", line); 609: printf(s, p1, p2, p3, p4, p5, p6); 610: putchar('\n'); 611: flush(); 612: fout = f; 613: } 614: 615: psoct(an) 616: { 617: register int n, sign; 618: 619: sign = 0; 620: if ((n = an) < 0) { 621: n = -n; 622: sign = '-'; 623: } 624: printf("%c%o", sign, n); 625: } 626: 627: /* 628: * Read in an intermediate file. 629: */ 630: getree() 631: { 632: struct tnode *expstack[20]; 633: register struct tnode **sp; 634: register t, op; 635: static char s[9]; 636: struct swtab *swp; 637: 638: spacep = treespace; 639: sp = expstack; 640: for (;;) { 641: if (sp >= &expstack[20]) 642: error("Stack botch"); 643: op = getw(ascbuf); 644: if ((op&0177400) != 0177000) { 645: error("Intermediate file error"); 646: exit(1); 647: } 648: switch(op =& 0377) { 649: 650: case EOF: 651: return; 652: 653: case BDATA: 654: printf(".byte "); 655: seq(','); 656: break; 657: 658: case WDATA: 659: seq(';'); 660: break; 661: 662: case PROG: 663: printf(".text\n"); 664: break; 665: 666: case DATA: 667: printf(".data\n"); 668: break; 669: 670: case BSS: 671: printf(".bss\n"); 672: break; 673: 674: case SYMDEF: 675: printf(".globl _%s\n", outname(s)); 676: break; 677: 678: case RETRN: 679: printf("jmp cret\n"); 680: break; 681: 682: case CSPACE: 683: t = outname(s); 684: printf(".comm _%s,%o\n", t, getw(ascbuf)); 685: break; 686: 687: case SSPACE: 688: printf(".=.+%o\n", getw(ascbuf)); 689: break; 690: 691: case EVEN: 692: printf(".even\n"); 693: break; 694: 695: case SAVE: 696: printf("jsr r5,csv\n"); 697: t = getw(ascbuf)-6; 698: if (t==2) 699: printf("tst -(sp)\n"); 700: else if (t > 2) 701: printf("sub $%o,sp\n", t); 702: break; 703: 704: case PROFIL: 705: t = getw(ascbuf); 706: printf("mov $L%d,r0\njsr pc,mcount\n", t); 707: printf(".bss\nL%d:.=.+2\n.text\n", t); 708: break; 709: 710: case SNAME: 711: t = outname(s); 712: printf("~%s=L%d\n", t, getw(ascbuf)); 713: break; 714: 715: case ANAME: 716: t = outname(s); 717: printf("~%s=%o\n", t, getw(ascbuf)); 718: break; 719: 720: case RNAME: 721: t = outname(s); 722: printf("~%s=r%d\n", t, getw(ascbuf)); 723: break; 724: 725: case SWIT: 726: t = getw(ascbuf); 727: line = getw(ascbuf); 728: swp = treespace; 729: while (swp->swlab = getw(ascbuf)) { 730: swp->swval = getw(ascbuf); 731: swp++; 732: } 733: pswitch(treespace, swp, t); 734: break; 735: 736: case EXPR: 737: line = getw(ascbuf); 738: if (sp != &expstack[1]) { 739: error("Expression input botch\n"); 740: exit(1); 741: } 742: nstack = 0; 743: rcexpr(optim(*--sp), efftab, 0); 744: spacep = treespace; 745: break; 746: 747: case NAME: 748: t = getw(ascbuf); 749: if (t==EXTERN) { 750: t = getw(ascbuf); 751: *sp = block(6, NAME, t, 0, EXTERN, 0, 0,0,0,0); 752: outname(&(*sp)->nloc); 753: sp++; 754: break; 755: } 756: *sp = block(3, NAME, 0, 0, t, 0, 0); 757: (*sp)->type = getw(ascbuf); 758: (*sp)->nloc = getw(ascbuf); 759: sp++; 760: break; 761: 762: case CON: 763: case SFCON: 764: case FCON: 765: t = getw(ascbuf); 766: *sp++ = block(1, op, t, 0, getw(ascbuf)); 767: break; 768: 769: case FSEL: 770: t = getw(ascbuf); 771: sp[-1] = block(2, op, t, 0, sp[-1], getw(ascbuf)); 772: break; 773: 774: case NULL: 775: *sp++ = block(0, 0, 0, 0); 776: break; 777: 778: case CBRANCH: 779: t = getw(ascbuf); 780: sp[-1] = block(1, CBRANCH, sp[-1], t, getw(ascbuf)); 781: break; 782: 783: case LABEL: 784: label(getw(ascbuf)); 785: break; 786: 787: case NLABEL: 788: printf("_%s:\n", outname(s)); 789: break; 790: 791: case RLABEL: 792: t = outname(s); 793: printf("_%s:\n~~%s:\n", t, t); 794: break; 795: 796: case BRANCH: 797: branch(getw(ascbuf), 0); 798: break; 799: 800: case SETREG: 801: nreg = getw(ascbuf)-1; 802: break; 803: 804: default: 805: if (opdope[op]&BINARY) { 806: if (sp < &expstack[1]) { 807: error("Binary expression botch"); 808: exit(1); 809: } 810: t = *--sp; 811: *sp++ = block(2, op, getw(ascbuf), 0, *--sp, t); 812: } else { 813: sp[-1] = block(1, op, getw(ascbuf), 0, sp[-1]); 814: } 815: break; 816: } 817: } 818: } 819: 820: outname(s) 821: { 822: register char *p, c; 823: register n; 824: 825: p = s; 826: n = 0; 827: while (c = getc(ascbuf)) { 828: *p++ = c; 829: n++; 830: } 831: while (n++ < 8) 832: *p++ = 0; 833: return(s); 834: } 835: 836: seq(c) 837: { 838: register o; 839: 840: if (getw(ascbuf) == 0) 841: return; 842: for (;;) { 843: printf("%o", getw(ascbuf)); 844: if ((o = getw(ascbuf)) != 1) 845: break; 846: printf("%c", c); 847: } 848: printf("\n"); 849: }