|
|
1.1 ! root 1: /* ! 2: * C compiler ! 3: */ ! 4: ! 5: #include "c1.h" ! 6: ! 7: max(a, b) ! 8: { ! 9: if (a>b) ! 10: return(a); ! 11: return(b); ! 12: } ! 13: ! 14: degree(t) ! 15: register union tree *t; ! 16: { ! 17: register union tree *t1; ! 18: ! 19: if (t==NULL || t->t.op==0) ! 20: return(0); ! 21: if (t->t.op == CON) ! 22: return(-3); ! 23: if (t->t.op == AMPER) ! 24: return(-2); ! 25: if (t->t.op==ITOL) { ! 26: if ((t1 = isconstant(t)) && (t1->c.value>=0 || uns(t1))) ! 27: return(-2); ! 28: if (uns(t1 = t->t.tr1) && opdope[t1->t.op]&LEAF) ! 29: return(-1); ! 30: } ! 31: if ((opdope[t->t.op] & LEAF) != 0) { ! 32: if (t->t.type==CHAR || t->t.type==UNCHAR || t->t.type==FLOAT) ! 33: return(1); ! 34: return(0); ! 35: } ! 36: return(t->t.degree); ! 37: } ! 38: ! 39: pname(p, flag) ! 40: register union tree *p; ! 41: { ! 42: register i; ! 43: ! 44: loop: ! 45: switch(p->t.op) { ! 46: ! 47: case LCON: ! 48: printf("$%o", flag<=10? UNS(p->l.lvalue>>16): ! 49: UNS(p->l.lvalue)); ! 50: return; ! 51: ! 52: case SFCON: ! 53: case CON: ! 54: printf("$"); ! 55: psoct(p->c.value); ! 56: return; ! 57: ! 58: case FCON: ! 59: printf("L%d", (p->c.value>0? p->c.value: -p->c.value)); ! 60: return; ! 61: ! 62: case NAME: ! 63: i = p->n.offset; ! 64: if (flag>10) ! 65: i += 2; ! 66: if (i) { ! 67: psoct(i); ! 68: if (p->n.class!=OFFS) ! 69: putchar('+'); ! 70: if (p->n.class==REG) ! 71: regerr(); ! 72: } ! 73: switch(p->n.class) { ! 74: ! 75: case SOFFS: ! 76: case XOFFS: ! 77: pbase(p); ! 78: ! 79: case OFFS: ! 80: printf("(r%d)", p->n.regno); ! 81: return; ! 82: ! 83: case EXTERN: ! 84: case STATIC: ! 85: pbase(p); ! 86: return; ! 87: ! 88: case REG: ! 89: printf("r%d", p->n.nloc); ! 90: return; ! 91: ! 92: } ! 93: error("Compiler error: pname"); ! 94: return; ! 95: ! 96: case AMPER: ! 97: putchar('$'); ! 98: p = p->t.tr1; ! 99: if (p->t.op==NAME && p->n.class==REG) ! 100: regerr(); ! 101: goto loop; ! 102: ! 103: case AUTOI: ! 104: printf("(r%d)%s", p->n.nloc, flag==1?"":"+"); ! 105: return; ! 106: ! 107: case AUTOD: ! 108: printf("%s(r%d)", flag==2?"":"-", p->n.nloc); ! 109: return; ! 110: ! 111: case STAR: ! 112: p = p->t.tr1; ! 113: putchar('*'); ! 114: goto loop; ! 115: ! 116: } ! 117: error("compiler error: bad pname"); ! 118: } ! 119: ! 120: regerr() ! 121: { ! 122: error("Illegal use of register"); ! 123: } ! 124: ! 125: pbase(p) ! 126: register union tree *p; ! 127: { ! 128: ! 129: if (p->n.class==SOFFS || p->n.class==STATIC) ! 130: printf("L%d", p->n.nloc); ! 131: else ! 132: printf("%.8s", p->x.name); ! 133: } ! 134: ! 135: xdcalc(p, nrleft) ! 136: register union tree *p; ! 137: { ! 138: register d; ! 139: ! 140: if (p==NULL) ! 141: return(0); ! 142: d = dcalc(p, nrleft); ! 143: if (d<20 && (p->t.type==CHAR || p->t.type==UNCHAR)) { ! 144: if (nrleft>=1) ! 145: d = 20; ! 146: else ! 147: d = 24; ! 148: } ! 149: return(d); ! 150: } ! 151: ! 152: dcalc(p, nrleft) ! 153: register union tree *p; ! 154: { ! 155: register union tree *p1; ! 156: ! 157: if (p==NULL) ! 158: return(0); ! 159: switch (p->t.op) { ! 160: ! 161: case NAME: ! 162: if (p->n.class==REG && p->n.type!=CHAR && p->n.type!=UNCHAR) ! 163: return(9); ! 164: ! 165: case AMPER: ! 166: case FCON: ! 167: case LCON: ! 168: case AUTOI: ! 169: case AUTOD: ! 170: return(12); ! 171: ! 172: case CON: ! 173: case SFCON: ! 174: if (p->c.value==0) ! 175: return(4); ! 176: if (p->c.value==1) ! 177: return(5); ! 178: if (p->c.value > 0) ! 179: return(8); ! 180: return(12); ! 181: ! 182: case STAR: ! 183: p1 = p->t.tr1; ! 184: if (p1->t.op==NAME||p1->t.op==CON||p1->t.op==AUTOI||p1->t.op==AUTOD) ! 185: if (p->t.type!=LONG) ! 186: return(12); ! 187: } ! 188: if (p->t.type==LONG) ! 189: nrleft--; ! 190: return(p->t.degree <= nrleft? 20: 24); ! 191: } ! 192: ! 193: notcompat(p, ast, deg, op) ! 194: register union tree *p; ! 195: { ! 196: unsigned register at, st; ! 197: ! 198: at = p->t.type; ! 199: /* ! 200: * an e or n UNCHAR is to be considered an UNSIGNED, ! 201: * as long as it is not pointed to. ! 202: */ ! 203: if (at==UNCHAR && deg<0100 && deg>=20) ! 204: at = UNSIGN; ! 205: st = ast; ! 206: if (st==0) /* word, byte */ ! 207: return(at!=CHAR && at!=INT && at!=UNSIGN && at<PTR); ! 208: if (st==1) /* word */ ! 209: return(at!=INT && at!=UNSIGN && at<PTR); ! 210: if (st==9 && (at&XTYPE)) ! 211: return(0); ! 212: st -= 2; ! 213: if ((at&(~(TYPE+XTYPE))) != 0) ! 214: at = 020; ! 215: if ((at&(~TYPE)) != 0) ! 216: at = at&TYPE | 020; ! 217: if (st==FLOAT && at==DOUBLE) ! 218: at = FLOAT; ! 219: if (p->t.op==NAME && p->n.class==REG && op==ASSIGN && st==CHAR) ! 220: return(0); ! 221: return(st != at); ! 222: } ! 223: ! 224: prins(op, c, itable) ! 225: struct instab *itable; ! 226: { ! 227: register struct instab *insp; ! 228: register char *ip; ! 229: ! 230: for (insp=itable; insp->iop != 0; insp++) { ! 231: if (insp->iop == op) { ! 232: ip = c? insp->str2: insp->str1; ! 233: if (ip==0) ! 234: break; ! 235: printf("%s", ip); ! 236: return; ! 237: } ! 238: } ! 239: error("No match' for op %d", op); ! 240: } ! 241: ! 242: collcon(p) ! 243: register union tree *p; ! 244: { ! 245: register op; ! 246: ! 247: if (p==NULL) ! 248: return(0); ! 249: if (p->t.op==STAR) { ! 250: if (p->t.type==LONG+PTR) /* avoid *x(r); *x+2(r) */ ! 251: return(0); ! 252: p = p->t.tr1; ! 253: } ! 254: if (p->t.op==PLUS) { ! 255: op = p->t.tr2->t.op; ! 256: if (op==CON || op==AMPER) ! 257: return(1); ! 258: } ! 259: return(0); ! 260: } ! 261: ! 262: isfloat(t) ! 263: register union tree *t; ! 264: { ! 265: ! 266: if ((opdope[t->t.op]&RELAT)!=0) ! 267: t = t->t.tr1; ! 268: if (t->t.type==FLOAT || t->t.type==DOUBLE) { ! 269: nfloat = 1; ! 270: return('f'); ! 271: } ! 272: return(0); ! 273: } ! 274: ! 275: oddreg(t, reg) ! 276: register union tree *t; ! 277: register reg; ! 278: { ! 279: ! 280: if (!isfloat(t)) { ! 281: if (opdope[t->t.op]&RELAT) { ! 282: if (t->t.tr1->t.type==LONG) ! 283: return((reg+1) & ~01); ! 284: return(reg); ! 285: } ! 286: switch(t->t.op) { ! 287: case LLSHIFT: ! 288: case ASLSHL: ! 289: case PTOI: ! 290: return((reg+1)&~01); ! 291: ! 292: case DIVIDE: ! 293: case MOD: ! 294: case ASDIV: ! 295: case ASMOD: ! 296: case ULSH: ! 297: case ASULSH: ! 298: reg++; ! 299: ! 300: case TIMES: ! 301: case ASTIMES: ! 302: return(reg|1); ! 303: } ! 304: } ! 305: return(reg); ! 306: } ! 307: ! 308: arlength(t) ! 309: { ! 310: if (t>=PTR) ! 311: return(2); ! 312: switch(t) { ! 313: ! 314: case INT: ! 315: case CHAR: ! 316: case UNSIGN: ! 317: case UNCHAR: ! 318: return(2); ! 319: ! 320: case LONG: ! 321: return(4); ! 322: ! 323: case FLOAT: ! 324: case DOUBLE: ! 325: return(8); ! 326: } ! 327: error("botch: peculiar type %d", t); ! 328: return(1024); ! 329: } ! 330: ! 331: /* ! 332: * Strings for switch code. ! 333: */ ! 334: ! 335: char dirsw[] = {"\ ! 336: cmp r0,$%o\n\ ! 337: jhi L%d\n\ ! 338: asl r0\n\ ! 339: jmp *L%d(r0)\n\ ! 340: .data\n\ ! 341: L%d:\ ! 342: " }; ! 343: ! 344: char hashsw[] = {"\ ! 345: mov r0,r1\n\ ! 346: clr r0\n\ ! 347: div $%o,r0\n\ ! 348: asl r1\n\ ! 349: jmp *L%d(r1)\n\ ! 350: .data\n\ ! 351: L%d:\ ! 352: "}; ! 353: ! 354: /* ! 355: * If the unsigned casts below won't compile, ! 356: * try using the calls to lrem and ldiv. ! 357: */ ! 358: ! 359: pswitch(afp, alp, deflab) ! 360: struct swtab *afp, *alp; ! 361: { ! 362: int ncase, i, j, tabs, worst, best, range; ! 363: register struct swtab *swp, *fp, *lp; ! 364: int *poctab; ! 365: ! 366: fp = afp; ! 367: lp = alp; ! 368: if (fp==lp) { ! 369: printf("jbr L%d\n", deflab); ! 370: return; ! 371: } ! 372: isn++; ! 373: if (sort(fp, lp)) ! 374: return; ! 375: ncase = lp-fp; ! 376: lp--; ! 377: range = lp->swval - fp->swval; ! 378: /* direct switch */ ! 379: if (range>0 && range <= 3*ncase) { ! 380: if (fp->swval) ! 381: printf("sub $%o,r0\n", UNS(fp->swval)); ! 382: printf(dirsw, UNS(range), deflab, isn, isn); ! 383: isn++; ! 384: for (i=fp->swval; ; i++) { ! 385: if (i==fp->swval) { ! 386: printf("L%d\n", fp->swlab); ! 387: if (fp==lp) ! 388: break; ! 389: fp++; ! 390: } else ! 391: printf("L%d\n", deflab); ! 392: } ! 393: printf(".text\n"); ! 394: return; ! 395: } ! 396: /* simple switch */ ! 397: if (ncase<10) { ! 398: for (fp = afp; fp<=lp; fp++) ! 399: breq(fp->swval, fp->swlab); ! 400: printf("jbr L%d\n", deflab); ! 401: return; ! 402: } ! 403: /* hash switch */ ! 404: best = 077777; ! 405: poctab = (int *)getblk(((ncase+2)/2) * sizeof(*poctab)); ! 406: for (i=ncase/4; i<=ncase/2; i++) { ! 407: for (j=0; j<i; j++) ! 408: poctab[j] = 0; ! 409: for (swp=fp; swp<=lp; swp++) ! 410: /* lrem(0, swp->swval, i) */ ! 411: poctab[(unsigned)swp->swval%i]++; ! 412: worst = 0; ! 413: for (j=0; j<i; j++) ! 414: if (poctab[j]>worst) ! 415: worst = poctab[j]; ! 416: if (i*worst < best) { ! 417: tabs = i; ! 418: best = i*worst; ! 419: } ! 420: } ! 421: i = isn++; ! 422: printf(hashsw, UNS(tabs), i, i); ! 423: isn++; ! 424: for (i=0; i<tabs; i++) ! 425: printf("L%d\n", isn+i); ! 426: printf(".text\n"); ! 427: for (i=0; i<tabs; i++) { ! 428: printf("L%d:", isn++); ! 429: for (swp=fp; swp<=lp; swp++) { ! 430: /* lrem(0, swp->swval, tabs) */ ! 431: if ((unsigned)swp->swval%tabs == i) { ! 432: /* ldiv(0, swp->swval, tabs) */ ! 433: breq((int)((unsigned)swp->swval/tabs), swp->swlab); ! 434: } ! 435: } ! 436: printf("jbr L%d\n", deflab); ! 437: } ! 438: } ! 439: ! 440: breq(v, l) ! 441: { ! 442: if (v==0) ! 443: printf("tst r0\n"); ! 444: else ! 445: printf("cmp r0,$%o\n", UNS(v)); ! 446: printf("jeq L%d\n", l); ! 447: } ! 448: ! 449: sort(afp, alp) ! 450: struct swtab *afp, *alp; ! 451: { ! 452: register struct swtab *cp, *fp, *lp; ! 453: int intch, t; ! 454: ! 455: fp = afp; ! 456: lp = alp; ! 457: while (fp < --lp) { ! 458: intch = 0; ! 459: for (cp=fp; cp<lp; cp++) { ! 460: if (cp->swval == cp[1].swval) { ! 461: error("Duplicate case (%d)", cp->swval); ! 462: return(1); ! 463: } ! 464: if (cp->swval > cp[1].swval) { ! 465: intch++; ! 466: t = cp->swval; ! 467: cp->swval = cp[1].swval; ! 468: cp[1].swval = t; ! 469: t = cp->swlab; ! 470: cp->swlab = cp[1].swlab; ! 471: cp[1].swlab = t; ! 472: } ! 473: } ! 474: if (intch==0) ! 475: break; ! 476: } ! 477: return(0); ! 478: } ! 479: ! 480: ispow2(tree) ! 481: register union tree *tree; ! 482: { ! 483: register int d; ! 484: ! 485: if (!isfloat(tree) && tree->t.tr2->t.op==CON) { ! 486: d = tree->t.tr2->c.value; ! 487: if (d>1 && (d&(d-1))==0) ! 488: return(d); ! 489: } ! 490: return(0); ! 491: } ! 492: ! 493: union tree * ! 494: pow2(tree) ! 495: register union tree *tree; ! 496: { ! 497: register int d, i; ! 498: ! 499: if (d = ispow2(tree)) { ! 500: for (i=0; (d>>=1)!=0; i++); ! 501: tree->t.tr2->c.value = i; ! 502: switch (tree->t.op) { ! 503: ! 504: case TIMES: ! 505: tree->t.op = LSHIFT; ! 506: break; ! 507: ! 508: case ASTIMES: ! 509: tree->t.op = ASLSH; ! 510: break; ! 511: ! 512: case PTOI: ! 513: if (i==1 && tree->t.tr1->t.op==MINUS && !isconstant(tree->t.tr1->t.tr2)) { ! 514: tree->t.op = PTOI1; ! 515: tree->t.tr1 = tnode(LTOI, INT, tree->t.tr1, TNULL); ! 516: return(optim(tree)); ! 517: } ! 518: tree->t.op = LLSHIFT; ! 519: tree->t.tr2->c.value = -i; ! 520: i = tree->t.type; ! 521: tree->t.type = LONG; ! 522: tree = tnode(LTOI, i, tree, TNULL); ! 523: break; ! 524: ! 525: case DIVIDE: ! 526: tree->t.op = ULSH; ! 527: tree->t.tr2->c.value = -i; ! 528: break; ! 529: ! 530: case ASDIV: ! 531: tree->t.op = ASULSH; ! 532: tree->t.tr2->c.value = -i; ! 533: break; ! 534: ! 535: case MOD: ! 536: tree->t.op = AND; ! 537: tree->t.tr2->c.value = (1<<i)-1; ! 538: break; ! 539: ! 540: case ASMOD: ! 541: tree->t.op = ASAND; ! 542: tree->t.tr2->c.value = (1<<i)-1; ! 543: break; ! 544: ! 545: default: ! 546: error("pow2 botch"); ! 547: } ! 548: tree = optim(tree); ! 549: } ! 550: return(tree); ! 551: } ! 552: ! 553: cbranch(atree, lbl, cond, reg) ! 554: union tree *atree; ! 555: register lbl, reg; ! 556: { ! 557: int l1, op; ! 558: register union tree *tree; ! 559: ! 560: again: ! 561: if ((tree=atree)==NULL) ! 562: return; ! 563: switch(tree->t.op) { ! 564: ! 565: case LOGAND: ! 566: if (cond) { ! 567: cbranch(tree->t.tr1, l1=isn++, 0, reg); ! 568: cbranch(tree->t.tr2, lbl, 1, reg); ! 569: label(l1); ! 570: } else { ! 571: cbranch(tree->t.tr1, lbl, 0, reg); ! 572: cbranch(tree->t.tr2, lbl, 0, reg); ! 573: } ! 574: return; ! 575: ! 576: case LOGOR: ! 577: if (cond) { ! 578: cbranch(tree->t.tr1, lbl, 1, reg); ! 579: cbranch(tree->t.tr2, lbl, 1, reg); ! 580: } else { ! 581: cbranch(tree->t.tr1, l1=isn++, 1, reg); ! 582: cbranch(tree->t.tr2, lbl, 0, reg); ! 583: label(l1); ! 584: } ! 585: return; ! 586: ! 587: case EXCLA: ! 588: cbranch(tree->t.tr1, lbl, !cond, reg); ! 589: return; ! 590: ! 591: case SEQNC: ! 592: rcexpr(tree->t.tr1, efftab, reg); ! 593: atree = tree->t.tr2; ! 594: goto again; ! 595: ! 596: case ITOL: ! 597: tree = tree->t.tr1; ! 598: break; ! 599: ! 600: case QUEST: ! 601: l1 = isn; ! 602: isn += 2; ! 603: cbranch(tree->t.tr1, l1, 0, reg); ! 604: cbranch(tree->t.tr2->t.tr1, lbl, cond, reg); ! 605: branch(l1+1, 0, 0); ! 606: label(l1); ! 607: cbranch(tree->t.tr2->t.tr2, lbl, cond, reg); ! 608: label(l1+1); ! 609: return; ! 610: ! 611: } ! 612: op = tree->t.op; ! 613: if (opdope[op]&RELAT ! 614: && tree->t.tr1->t.op==ITOL && tree->t.tr2->t.op==ITOL ! 615: && uns(tree->t.tr1->t.tr1) == uns(tree->t.tr2->t.tr1)) { ! 616: tree->t.tr1 = tree->t.tr1->t.tr1; ! 617: tree->t.tr2 = tree->t.tr2->t.tr1; ! 618: if (op>=LESSEQ && op<=GREAT ! 619: && uns(tree->t.tr1)) ! 620: tree->t.op = op = op+LESSEQP-LESSEQ; ! 621: } ! 622: if (tree->t.type==LONG ! 623: || opdope[op]&RELAT&&tree->t.tr1->t.type==LONG) { ! 624: longrel(tree, lbl, cond, reg); ! 625: return; ! 626: } ! 627: rcexpr(tree, cctab, reg); ! 628: op = tree->t.op; ! 629: if ((opdope[op]&RELAT)==0) ! 630: op = NEQUAL; ! 631: else { ! 632: l1 = tree->t.tr2->t.op; ! 633: if ((l1==CON || l1==SFCON) && tree->t.tr2->c.value==0) ! 634: op += 200; /* special for ptr tests */ ! 635: else ! 636: op = maprel[op-EQUAL]; ! 637: } ! 638: if (isfloat(tree)) ! 639: printf("cfcc\n"); ! 640: branch(lbl, op, !cond); ! 641: } ! 642: ! 643: branch(lbl, aop, c) ! 644: { ! 645: register op; ! 646: ! 647: if(op=aop) ! 648: prins(op, c, branchtab); ! 649: else ! 650: printf("jbr"); ! 651: printf("\tL%d\n", lbl); ! 652: } ! 653: ! 654: longrel(atree, lbl, cond, reg) ! 655: union tree *atree; ! 656: { ! 657: int xl1, xl2, xo, xz; ! 658: register int op, isrel; ! 659: register union tree *tree; ! 660: ! 661: if (reg&01) ! 662: reg++; ! 663: reorder(&atree, cctab, reg); ! 664: tree = atree; ! 665: isrel = 0; ! 666: if (opdope[tree->t.op]&RELAT) { ! 667: isrel++; ! 668: op = tree->t.op; ! 669: } else ! 670: op = NEQUAL; ! 671: if (!cond) ! 672: op = notrel[op-EQUAL]; ! 673: xl1 = xlab1; ! 674: xl2 = xlab2; ! 675: xo = xop; ! 676: xlab1 = lbl; ! 677: xlab2 = 0; ! 678: xop = op; ! 679: xz = xzero; ! 680: xzero = !isrel || tree->t.tr2->t.op==ITOL && tree->t.tr2->t.tr1->t.op==CON ! 681: && tree->t.tr2->t.tr1->c.value==0; ! 682: if (tree->t.op==ANDN) { ! 683: tree->t.op = TAND; ! 684: tree->t.tr2 = optim(tnode(COMPL, LONG, tree->t.tr2, TNULL)); ! 685: } ! 686: if (cexpr(tree, cctab, reg) < 0) { ! 687: reg = rcexpr(tree, regtab, reg); ! 688: printf("ashc $0,r%d\n", reg); ! 689: branch(xlab1, op, 0); ! 690: } ! 691: xlab1 = xl1; ! 692: xlab2 = xl2; ! 693: xop = xo; ! 694: xzero = xz; ! 695: } ! 696: ! 697: /* ! 698: * Tables for finding out how best to do long comparisons. ! 699: * First dimen is whether or not the comparison is with 0. ! 700: * Second is which test: e.g. a>b-> ! 701: * cmp a,b ! 702: * bgt YES (first) ! 703: * blt NO (second) ! 704: * cmp a+2,b+2 ! 705: * bhi YES (third) ! 706: * NO: ... ! 707: * Note some tests may not be needed. ! 708: */ ! 709: char lrtab[2][3][6] = { ! 710: 0, NEQUAL, LESS, LESS, GREAT, GREAT, ! 711: NEQUAL, 0, GREAT, GREAT, LESS, LESS, ! 712: EQUAL, NEQUAL, LESSEQP,LESSP, GREATQP,GREATP, ! 713: ! 714: 0, NEQUAL, LESS, LESS, GREATEQ,GREAT, ! 715: NEQUAL, 0, GREAT, 0, 0, LESS, ! 716: EQUAL, NEQUAL, EQUAL, 0, 0, NEQUAL, ! 717: }; ! 718: ! 719: xlongrel(f) ! 720: { ! 721: register int op, bno; ! 722: ! 723: op = xop; ! 724: if (f==0) { ! 725: if (bno = lrtab[xzero][0][op-EQUAL]) ! 726: branch(xlab1, bno, 0); ! 727: if (bno = lrtab[xzero][1][op-EQUAL]) { ! 728: xlab2 = isn++; ! 729: branch(xlab2, bno, 0); ! 730: } ! 731: if (lrtab[xzero][2][op-EQUAL]==0) ! 732: return(1); ! 733: } else { ! 734: branch(xlab1, lrtab[xzero][2][op-EQUAL], 0); ! 735: if (xlab2) ! 736: label(xlab2); ! 737: } ! 738: return(0); ! 739: } ! 740: ! 741: label(l) ! 742: { ! 743: printf("L%d:", l); ! 744: } ! 745: ! 746: popstk(a) ! 747: { ! 748: switch(a) { ! 749: ! 750: case 0: ! 751: return; ! 752: ! 753: case 2: ! 754: printf("tst (sp)+\n"); ! 755: return; ! 756: ! 757: case 4: ! 758: printf("cmp (sp)+,(sp)+\n"); ! 759: return; ! 760: } ! 761: printf("add $%o,sp\n", UNS(a)); ! 762: } ! 763: ! 764: /* VARARGS1 */ ! 765: error(s, p1, p2, p3, p4, p5, p6) ! 766: char *s; ! 767: { ! 768: ! 769: nerror++; ! 770: fprintf(stderr, "%d: ", line); ! 771: fprintf(stderr, s, p1, p2, p3, p4, p5, p6); ! 772: putc('\n', stderr); ! 773: } ! 774: ! 775: psoct(an) ! 776: { ! 777: register int n; ! 778: register char *sign; ! 779: ! 780: sign = ""; ! 781: if ((n = an) < 0) { ! 782: n = -n; ! 783: sign = "-"; ! 784: } ! 785: printf("%s%o", sign, n); ! 786: } ! 787: ! 788: /* ! 789: * Read in an intermediate file. ! 790: */ ! 791: #define STKS 100 ! 792: getree() ! 793: { ! 794: union tree *expstack[STKS]; ! 795: union tree **sp; ! 796: register union tree *tp; ! 797: register t, op; ! 798: static char s[9]; ! 799: struct swtab *swp; ! 800: double atof(); ! 801: long outloc; ! 802: char numbuf[64]; ! 803: int lbl, cond, lbl2, lbl3; ! 804: ! 805: curbase = funcbase; ! 806: sp = expstack; ! 807: for (;;) { ! 808: if (sp >= &expstack[STKS]) ! 809: error("Stack overflow botch"); ! 810: op = geti(); ! 811: if ((op&0177400) != 0177000) { ! 812: error("Intermediate file error"); ! 813: exit(1); ! 814: } ! 815: lbl = 0; ! 816: switch(op &= 0377) { ! 817: ! 818: case SINIT: ! 819: printf("%o\n", UNS(geti())); ! 820: break; ! 821: ! 822: case EOFC: ! 823: return; ! 824: ! 825: case BDATA: ! 826: if (geti() == 1) { ! 827: printf(".byte "); ! 828: for (;;) { ! 829: printf("%o", UNS(geti())); ! 830: if (geti() != 1) ! 831: break; ! 832: printf(","); ! 833: } ! 834: printf("\n"); ! 835: } ! 836: break; ! 837: ! 838: case PROG: ! 839: printf(".text\n"); ! 840: break; ! 841: ! 842: case DATA: ! 843: printf(".data\n"); ! 844: break; ! 845: ! 846: case BSS: ! 847: printf(".bss\n"); ! 848: break; ! 849: ! 850: case SYMDEF: ! 851: outname(s); ! 852: printf(".globl%s%.8s\n", s[0]?" ":"", s); ! 853: sfuncr.nloc = 0; ! 854: break; ! 855: ! 856: case RETRN: ! 857: printf("jmp cret\n"); ! 858: break; ! 859: ! 860: case CSPACE: ! 861: outname(s); ! 862: printf(".comm %.8s,%o\n", s, UNS(geti())); ! 863: break; ! 864: ! 865: case SSPACE: ! 866: printf(".=.+%o\n", UNS(t=geti())); ! 867: totspace += (unsigned)t; ! 868: break; ! 869: ! 870: case EVEN: ! 871: printf(".even\n"); ! 872: break; ! 873: ! 874: case SAVE: ! 875: printf("jsr r0,csav\n"); ! 876: break; ! 877: ! 878: case SETSTK: ! 879: t = geti()-6; ! 880: if (t==2) ! 881: printf("tst -(sp)\n"); ! 882: else if (t != 0) ! 883: printf("sub $%o,sp\n", UNS(t)); ! 884: break; ! 885: ! 886: case PROFIL: ! 887: t = geti(); ! 888: printf("mov $L%d,r0\njsr pc,mcount\n", t); ! 889: printf(".bss\nL%d:.=.+2\n.text\n", t); ! 890: break; ! 891: ! 892: case SNAME: ! 893: outname(s); ! 894: printf("~%s=L%d\n", s+1, geti()); ! 895: break; ! 896: ! 897: case ANAME: ! 898: outname(s); ! 899: printf("~%s=%o\n", s+1, UNS(geti())); ! 900: break; ! 901: ! 902: case RNAME: ! 903: outname(s); ! 904: printf("~%s=r%d\n", s+1, geti()); ! 905: break; ! 906: ! 907: case SWIT: ! 908: t = geti(); ! 909: line = geti(); ! 910: curbase = funcbase; ! 911: while(swp=(struct swtab *)getblk(sizeof(*swp)), swp->swlab = geti()) ! 912: swp->swval = geti(); ! 913: pswitch((struct swtab *)funcbase, swp, t); ! 914: break; ! 915: ! 916: case C3BRANCH: /* for fortran [sic] */ ! 917: lbl = geti(); ! 918: lbl2 = geti(); ! 919: lbl3 = geti(); ! 920: goto xpr; ! 921: ! 922: case CBRANCH: ! 923: lbl = geti(); ! 924: cond = geti(); ! 925: ! 926: case EXPR: ! 927: xpr: ! 928: line = geti(); ! 929: if (sp != &expstack[1]) { ! 930: error("Expression input botch"); ! 931: exit(1); ! 932: } ! 933: --sp; ! 934: regpanic = 0; ! 935: if (setjmp(jmpbuf)) { ! 936: regpanic = 10; ! 937: fseek(stdout, outloc, 0); ! 938: } ! 939: nstack = 0; ! 940: panicposs = 0; ! 941: *sp = tp = optim(*sp); ! 942: if (regpanic==0 && panicposs) ! 943: outloc = ftell(stdout); ! 944: if (op==CBRANCH) ! 945: cbranch(tp, lbl, cond, 0); ! 946: else if (op==EXPR) ! 947: rcexpr(tp, efftab, 0); ! 948: else { ! 949: if (tp->t.type==LONG) { ! 950: rcexpr(tnode(RFORCE, tp->t.type, tp, TNULL), efftab, 0); ! 951: printf("ashc $0,r0\n"); ! 952: } else { ! 953: rcexpr(tp, cctab, 0); ! 954: if (isfloat(tp)) ! 955: printf("cfcc\n"); ! 956: } ! 957: printf("jgt L%d\n", lbl3); ! 958: printf("jlt L%d\njbr L%d\n", lbl, lbl2); ! 959: } ! 960: curbase = funcbase; ! 961: break; ! 962: ! 963: case NAME: ! 964: t = geti(); ! 965: if (t==EXTERN) { ! 966: tp = getblk(sizeof(struct xtname)); ! 967: tp->t.type = geti(); ! 968: outname(tp->x.name); ! 969: } else { ! 970: tp = getblk(sizeof(struct tname)); ! 971: tp->t.type = geti(); ! 972: tp->n.nloc = geti(); ! 973: } ! 974: tp->t.op = NAME; ! 975: tp->n.class = t; ! 976: tp->n.regno = 0; ! 977: tp->n.offset = 0; ! 978: *sp++ = tp; ! 979: break; ! 980: ! 981: case CON: ! 982: t = geti(); ! 983: *sp++ = tconst(geti(), t); ! 984: break; ! 985: ! 986: case LCON: ! 987: geti(); /* ignore type, assume long */ ! 988: t = geti(); ! 989: op = geti(); ! 990: if (t==0 && op>=0 || t == -1 && op<0) { ! 991: *sp++ = tnode(ITOL, LONG, tconst(op, INT), TNULL); ! 992: break; ! 993: } ! 994: tp = getblk(sizeof(struct lconst)); ! 995: tp->t.op = LCON; ! 996: tp->t.type = LONG; ! 997: tp->l.lvalue = ((long)t<<16) + UNS(op); /* nonportable */ ! 998: *sp++ = tp; ! 999: break; ! 1000: ! 1001: case FCON: ! 1002: t = geti(); ! 1003: outname(numbuf); ! 1004: tp = getblk(sizeof(struct ftconst)); ! 1005: tp->t.op = FCON; ! 1006: tp->t.type = t; ! 1007: tp->f.value = isn++; ! 1008: tp->f.fvalue = atof(numbuf); ! 1009: *sp++ = tp; ! 1010: break; ! 1011: ! 1012: case FSEL: ! 1013: tp = tnode(FSEL, geti(), *--sp, TNULL); ! 1014: t = geti(); ! 1015: tp->t.tr2 = tnode(COMMA, INT, tconst(geti(), INT), tconst(t, INT)); ! 1016: if (tp->t.tr2->t.tr1->c.value==16) ! 1017: tp = paint(tp->t.tr1, tp->t.type); ! 1018: *sp++ = tp; ! 1019: break; ! 1020: ! 1021: case STRASG: ! 1022: tp = getblk(sizeof(struct fasgn)); ! 1023: tp->t.op = STRASG; ! 1024: tp->t.type = geti(); ! 1025: tp->F.mask = geti(); ! 1026: tp->t.tr1 = *--sp; ! 1027: tp->t.tr2 = NULL; ! 1028: *sp++ = tp; ! 1029: break; ! 1030: ! 1031: case NULLOP: ! 1032: *sp++ = tnode(0, 0, TNULL, TNULL); ! 1033: break; ! 1034: ! 1035: case LABEL: ! 1036: label(geti()); ! 1037: break; ! 1038: ! 1039: case NLABEL: ! 1040: outname(s); ! 1041: printf("%.8s:\n", s, s); ! 1042: break; ! 1043: ! 1044: case RLABEL: ! 1045: outname(s); ! 1046: printf("%.8s:\n~~%s:\n", s, s+1); ! 1047: break; ! 1048: ! 1049: case BRANCH: ! 1050: branch(geti(), 0, 0); ! 1051: break; ! 1052: ! 1053: case SETREG: ! 1054: nreg = geti()-1; ! 1055: break; ! 1056: ! 1057: default: ! 1058: if (opdope[op]&BINARY) { ! 1059: if (sp < &expstack[1]) { ! 1060: error("Binary expression botch"); ! 1061: exit(1); ! 1062: } ! 1063: tp = *--sp; ! 1064: *sp++ = tnode(op, geti(), *--sp, tp); ! 1065: } else ! 1066: sp[-1] = tnode(op, geti(), sp[-1], TNULL); ! 1067: break; ! 1068: } ! 1069: } ! 1070: } ! 1071: ! 1072: geti() ! 1073: { ! 1074: register short i; ! 1075: ! 1076: i = getchar(); ! 1077: i += getchar()<<8; ! 1078: return(i); ! 1079: } ! 1080: ! 1081: outname(s) ! 1082: register char *s; ! 1083: { ! 1084: register c; ! 1085: register n; ! 1086: ! 1087: n = 0; ! 1088: while (c = getchar()) { ! 1089: *s++ = c; ! 1090: n++; ! 1091: } ! 1092: do { ! 1093: *s++ = 0; ! 1094: } while (n++ < 8); ! 1095: } ! 1096: ! 1097: strasg(atp) ! 1098: union tree *atp; ! 1099: { ! 1100: register union tree *tp; ! 1101: register nwords, i; ! 1102: ! 1103: nwords = atp->F.mask/sizeof(short); ! 1104: tp = atp->t.tr1; ! 1105: if (tp->t.op != ASSIGN) { ! 1106: if (tp->t.op==RFORCE) { /* function return */ ! 1107: if (sfuncr.nloc==0) { ! 1108: sfuncr.nloc = isn++; ! 1109: printf(".bss\nL%d:.=.+%o\n.text\n", sfuncr.nloc, ! 1110: UNS(nwords*sizeof(short))); ! 1111: } ! 1112: atp->t.tr1 = tnode(ASSIGN, STRUCT, (union tree *)&sfuncr, tp->t.tr1); ! 1113: strasg(atp); ! 1114: printf("mov $L%d,r0\n", sfuncr.nloc); ! 1115: return; ! 1116: } ! 1117: if (tp->t.op==CALL) { ! 1118: rcexpr(tp, efftab, 0); ! 1119: return; ! 1120: } ! 1121: error("Illegal structure operation"); ! 1122: return; ! 1123: } ! 1124: tp->t.tr2 = strfunc(tp->t.tr2); ! 1125: if (nwords==1) ! 1126: paint(tp, INT); ! 1127: else if (nwords==sizeof(short)) ! 1128: paint(tp, LONG); ! 1129: else { ! 1130: if (tp->t.tr1->t.op!=NAME && tp->t.tr1->t.op!=STAR ! 1131: || tp->t.tr2->t.op!=NAME && tp->t.tr2->t.op!=STAR) { ! 1132: error("unimplemented structure assignment"); ! 1133: return; ! 1134: } ! 1135: tp->t.tr1 = tnode(AMPER, STRUCT+PTR, tp->t.tr1, TNULL); ! 1136: tp->t.tr2 = tnode(AMPER, STRUCT+PTR, tp->t.tr2, TNULL); ! 1137: tp->t.op = STRSET; ! 1138: tp->t.type = STRUCT+PTR; ! 1139: tp = optim(tp); ! 1140: rcexpr(tp, efftab, 0); ! 1141: if (nwords < 7) { ! 1142: for (i=0; i<nwords; i++) ! 1143: printf("mov (r1)+,(r0)+\n"); ! 1144: return; ! 1145: } ! 1146: if (nreg<=1) ! 1147: printf("mov r2,-(sp)\n"); ! 1148: printf("mov $%o,r2\n", UNS(nwords)); ! 1149: printf("L%d:mov (r1)+,(r0)+\ndec\tr2\njne\tL%d\n", isn, isn); ! 1150: isn++; ! 1151: if (nreg<=1) ! 1152: printf("mov (sp)+,r2\n"); ! 1153: return; ! 1154: } ! 1155: rcexpr(tp, efftab, 0); ! 1156: } ! 1157: ! 1158: /* ! 1159: * Reduce the degree-of-reference by one. ! 1160: * e.g. turn "ptr-to-int" into "int". ! 1161: */ ! 1162: decref(t) ! 1163: register t; ! 1164: { ! 1165: if ((t & ~TYPE) == 0) { ! 1166: error("Illegal indirection"); ! 1167: return(t); ! 1168: } ! 1169: return(((unsigned)t>>TYLEN) & ~TYPE | t&TYPE); ! 1170: } ! 1171: ! 1172: /* ! 1173: * Increase the degree of reference by ! 1174: * one; e.g. turn "int" to "ptr-to-int". ! 1175: */ ! 1176: incref(t) ! 1177: { ! 1178: return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR); ! 1179: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.