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