|
|
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.