Research V6 development
[unix-history] / usr / source / c / c11.c
CommitLineData
cac4f7ea
DR
1#
2/*
3 * C compiler
4 */
5
6#include "c1h.c"
7
8max(a, b)
9{
10 if (a>b)
11 return(a);
12 return(b);
13}
14
15degree(at)
16struct 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
36pname(ap, flag)
37struct tnode *ap;
38{
39 register i;
40 register struct tnode *p;
41
42 p = ap;
43loop:
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
114regerr()
115{
116 error("Illegal use of register");
117}
118
119pbase(ap)
120struct 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
131xdcalc(ap, nrleft)
132struct 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
148dcalc(ap, nrleft)
149struct 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
188notcompat(ap, ast, op)
189struct 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
213prins(op, c, itable)
214struct 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
231collcon(ap)
232struct 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
248isfloat(at)
249struct 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
263oddreg(t, areg)
264struct 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
284arlength(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
308char dirsw[] {"\
309cmp r0,$%o\n\
310jhi L%d\n\
311asl r0\n\
312jmp *L%d(r0)\n\
313.data\n\
314L%d:\
315" };
316
317char simpsw[] {"\
318mov $L%d,r1\n\
319mov r0,L%d\n\
320L%d:cmp r0,(r1)+\n\
321jne L%d\n\
322jmp *L%d-L%d(r1)\n\
323.data\n\
324L%d:\
325"};
326
327char hashsw[] {"\
328mov r0,r1\n\
329clr r0\n\
330div $%o,r0\n\
331asl r1\n\
332add $L%d,r1\n\
333mov r0,*(r1)+\n\
334mov (r1)+,r1\n\
335L%d:cmp r0,-(r1)\n\
336jne L%d\n\
337jmp *L%d-L%d(r1)\n\
338.data\n\
339L%d:\
340"};
341
342pswitch(afp, alp, deflab)
343struct 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 }
424esw:
425 printf(".text\n");
426}
427
428sort(afp, alp)
429struct 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
459ispow2(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
473pow2(atree)
474struct 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
492cbranch(atree, albl, cond, areg)
493struct 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
565branch(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
576label(l)
577{
578 printf("L%d:", l);
579}
580
581popstk(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
599error(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
615psoct(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 */
630getree()
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
820outname(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
836seq(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}