|
|
1.1 root 1: /*
2: * C compiler
3: */
4:
5: #include "c0.h"
6:
7: /*
8: * Called from tree, this routine takes the top 1, 2, or 3
9: * operands on the expression stack, makes a new node with
10: * the operator op, and puts it on the stack.
11: * Essentially all the work is in inserting
12: * appropriate conversions.
13: */
14: build(op)
15: {
16: register int t1;
17: int t2, t;
18: register union tree *p1, *p2, *p3;
19: int dope, leftc, cvn, pcvn;
20:
21: /*
22: * a[i] => *(a+i)
23: */
24: if (op==LBRACK) {
25: build(PLUS);
26: op = STAR;
27: }
28: dope = opdope[op];
29: t2 = INT;
30: if ((dope&BINARY)!=0) {
31: p2 = chkfun(disarray(*--cp));
32: if (p2)
33: t2 = p2->t.type;
34: }
35: p1 = *--cp;
36: /*
37: * sizeof gets turned into a number here.
38: */
39: if (op==SIZEOF) {
40: p1 = cblock(length(p1));
41: p1->c.type = UNSIGN;
42: *cp++ = p1;
43: return;
44: }
45: if (op!=AMPER) {
46: p1 = disarray(p1);
47: if (op!=CALL)
48: p1 = chkfun(p1);
49: }
50: t1 = p1->t.type;
51: if (t1==CHAR)
52: t1 = INT;
53: else if (t1==UNCHAR)
54: t1 = UNSIGN;
55: if (t2==CHAR)
56: t2 = INT;
57: else if (t2==UNCHAR)
58: t2 = UNSIGN;
59: pcvn = 0;
60: t = INT;
61: switch (op) {
62:
63: case CAST:
64: if ((t1&XTYPE)==FUNC || (t1&XTYPE)==ARRAY)
65: error("Disallowed conversion");
66: if (p1->t.type==UNCHAR) {
67: *cp++ = block(ETYPE, UNSIGN, (int *)NULL, (union str *)NULL,
68: TNULL, TNULL);
69: *cp++ = p2;
70: build(CAST);
71: *cp++ = cblock(0377);
72: build(AND);
73: return;
74: }
75: if (p2->t.type==CHAR || p2->t.type==UNCHAR)
76: p2 = block(PLUS, t2, (int *)NULL, (union str *)NULL,
77: p2, cblock(0));
78: break;
79:
80: /* end of expression */
81: case 0:
82: *cp++ = p1;
83: return;
84:
85: /* no-conversion operators */
86: case QUEST:
87: if (p2->t.op!=COLON)
88: error("Illegal conditional");
89: else
90: if (fold(QUEST, p1, p2))
91: return;
92:
93: case SEQNC:
94: t = t2;
95:
96: case COMMA:
97: case LOGAND:
98: case LOGOR:
99: *cp++ = block(op, t, p2->t.subsp, p2->t.strp, p1, p2);
100: return;
101:
102: case EXCLA:
103: t1 = INT;
104: break;
105:
106: case CALL:
107: if ((t1&XTYPE) != FUNC)
108: error("Call of non-function");
109: *cp++ = block(CALL,decref(t1),p1->t.subsp,p1->t.strp,p1,p2);
110: return;
111:
112: case STAR:
113: if ((t1&XTYPE) == FUNC)
114: error("Illegal indirection");
115: *cp++ = block(STAR, decref(t1), p1->t.subsp, p1->t.strp, p1, TNULL);
116: return;
117:
118: case AMPER:
119: if (p1->t.op==NAME || p1->t.op==STAR) {
120: *cp++ = block(op,incref(p1->t.type),p1->t.subsp,p1->t.strp,p1,TNULL);
121: return;
122: }
123: error("Illegal lvalue");
124: break;
125:
126: /*
127: * a.b goes to (&a)->b
128: */
129: case DOT:
130: if (p1->t.op==CALL && t1==STRUCT) {
131: t1 = incref(t1);
132: setype(p1, t1, p1);
133: } else {
134: *cp++ = p1;
135: build(AMPER);
136: p1 = *--cp;
137: }
138:
139: /*
140: * In a->b, a is given the type ptr-to-structure element;
141: * then the offset is added in without conversion;
142: * then * is tacked on to access the member.
143: */
144: case ARROW:
145: if (p2->t.op!=NAME || p2->t.tr1->n.hclass!=MOS) {
146: error("Illegal structure ref");
147: *cp++ = p1;
148: return;
149: }
150: p2 = structident(p1, p2);
151: t2 = p2->n.htype;
152: if (t2==INT && p2->t.tr1->n.hflag&FFIELD)
153: t2 = UNSIGN;
154: t = incref(t2);
155: chkw(p1, -1);
156: setype(p1, t, p2);
157: *cp++ = block(PLUS, t, p2->t.subsp, p2->t.strp,
158: p1, cblock(p2->t.tr1->n.hoffset));
159: build(STAR);
160: if (p2->t.tr1->n.hflag&FFIELD)
161: *cp++ = block(FSEL, UNSIGN, (int *)NULL, (union str *)NULL,
162: *--cp, p2->t.tr1->n.hstrp);
163: return;
164: }
165: if ((dope&LVALUE)!=0)
166: chklval(p1);
167: if ((dope&LWORD)!=0)
168: chkw(p1, LONG);
169: if ((dope&RWORD)!=0)
170: chkw(p2, LONG);
171: if ((t1==VOID && op!=CAST) || (t2==VOID && (op!=CAST || t1!=VOID))) {
172: error("Illegal use of void object");
173: t = t1 = t2 = INT;
174: }
175: if ((dope&BINARY)==0) {
176: if (op==ITOF)
177: t1 = DOUBLE;
178: else if (op==FTOI)
179: t1 = INT;
180: if (!fold(op, p1, (union tree *)NULL))
181: *cp++ = block(op, t1, p1->t.subsp, p1->t.strp, p1,TNULL);
182: return;
183: }
184: cvn = 0;
185: if (t1==STRUCT || t2==STRUCT) {
186: if (t1!=t2 || p1->t.strp != p2->t.strp)
187: error("Incompatible structures");
188: cvn = 0;
189: } else
190: cvn = cvtab[lintyp(t1)][lintyp(t2)];
191: leftc = (cvn>>4)&017;
192: cvn &= 017;
193: t = leftc? t2:t1;
194: if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN))
195: t = UNSIGN;
196: if (dope&ASSGOP || op==CAST) {
197: if (leftc && (op>=ASPLUS && op<=ASXOR)) {
198: assignop(op, p1, p2);
199: return;
200: }
201: t = t1;
202: if (op==ASSIGN) {
203: if (cvn==PTI) {
204: if (t1!=t2 || ((t1&TYPE)==STRUCT && p1->t.strp!=p2->t.strp)) {
205: error("Warning: mixed pointer assignment");
206: nerror--;
207: }
208: cvn = leftc = 0;
209: }
210: } else if (op==CAST) {
211: if (cvn==ITP||cvn==PTI)
212: cvn = leftc = 0;
213: else if (cvn==LTP) {
214: if (leftc==0)
215: cvn = LTI;
216: else {
217: cvn = ITL;
218: leftc = 0;
219: }
220: }
221: }
222: if (leftc)
223: cvn = leftc;
224: leftc = 0;
225: } else if (op==COLON || op==MAX || op==MIN) {
226: if (t1>=PTR && t1==t2)
227: cvn = 0;
228: if (op!=COLON && (t1>=PTR || t2>=PTR))
229: op += MAXP-MAX;
230: } else if (dope&RELAT) {
231: if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t2==UNSIGN)
232: && (t==INT||t==CHAR||t==UNSIGN)))
233: op += LESSEQP-LESSEQ;
234: if (cvn==ITP || cvn==PTI)
235: cvn = 0;
236: }
237: if (cvn==PTI) {
238: cvn = 0;
239: if (op==MINUS) {
240: pcvn++;
241: p1 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p1, TNULL);
242: p2 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p2, TNULL);
243: t = LONG;
244: } else {
245: if (t1!=t2 || (t1!=(PTR+CHAR) && t1!=(PTR+UNCHAR)))
246: cvn = XX;
247: }
248: }
249: if (cvn) {
250: if ((cvn==ITP || cvn==LTP) && (opdope[op]&PCVOK)==0) {
251: p3 = leftc? p1: p2;
252: if ((p3->t.op!=CON || p3->c.value!=0)
253: && (p3->t.op!=LCON || p3->l.lvalue!=0))
254: cvn = XX;
255: else
256: cvn = 0;
257: }
258: t1 = plength(p1);
259: t2 = plength(p2);
260: if (cvn==XX || (cvn==PTI&&t1!=t2))
261: error("Illegal conversion");
262: else if (leftc)
263: p1 = convert(p1, t, cvn, t2);
264: else
265: p2 = convert(p2, t, cvn, t1);
266: }
267: if (dope&RELAT)
268: t = INT;
269: if (t==FLOAT)
270: t = DOUBLE;
271: if (t==CHAR)
272: t = INT;
273: if (op==CAST) {
274: if (t!=DOUBLE && (t!=INT || p2->t.type!=CHAR || p2->t.type!=UNCHAR)) {
275: p2->t.type = t;
276: p2->t.subsp = p1->t.subsp;
277: p2->t.strp = p1->t.strp;
278: }
279: if (t==INT && p1->t.type==CHAR)
280: p2 = block(ITOC, INT, (int *)NULL, (union str *)NULL, p2, TNULL);
281: *cp++ = p2;
282: return;
283: }
284: if (pcvn)
285: t2 = plength(p1->t.tr1);
286: if (fold(op, p1, p2)==0) {
287: p3 = leftc?p2:p1;
288: *cp++ = block(op, t, p3->t.subsp, p3->t.strp, p1, p2);
289: }
290: if (pcvn) {
291: p1 = *--cp;
292: *cp++ = convert(p1, 0, PTI, t2);
293: }
294: }
295:
296: union tree *
297: structident(p1, p2)
298: register union tree *p1, *p2;
299: {
300: register struct nmlist *np;
301: int vartypes = 0, namesame = 1;
302:
303: np = (struct nmlist *)p2->t.tr1;
304: for (;;) {
305: if (namesame && p1->t.type==STRUCT+PTR && p1->t.strp == np->sparent) {
306: p2->t.type = np->htype;
307: p2->t.strp = np->hstrp;
308: p2->t.subsp = np->hsubsp;
309: p2->t.tr1 = (union tree *)np;
310: return(p2);
311: }
312: np = np->nextnm;
313: if (np==NULL)
314: break;
315: namesame = 0;
316: if (strncmp(p2->t.tr1->n.name, np->name, NCPS) != 0)
317: continue;
318: if ((p2->t.tr1->n.hflag&FKIND) != (np->hflag&FMOS))
319: continue;
320: namesame = 1;
321: if (p2->t.tr1->n.htype==np->htype && p2->t.tr1->n.hoffset==np->hoffset)
322: continue;
323: vartypes++;
324: }
325: if (vartypes)
326: error("Ambiguous structure reference for %.8s", p2->t.tr1->n.name);
327: else {
328: error("Warning: %.8s not member of cited struct/union", p2->t.tr1->n.name);
329: nerror--;
330: }
331: return(p2);
332: }
333:
334: /*
335: * Generate the appropriate conversion operator.
336: */
337: union tree *
338: convert(p, t, cvn, len)
339: union tree *p;
340: {
341: register int op;
342:
343: if (cvn==0)
344: return(p);
345: op = cvntab[cvn];
346: if (opdope[op]&BINARY) {
347: if (len==0)
348: error("Illegal conversion");
349: return(block(op, t, (int *)NULL, (union str *)NULL, p, cblock(len)));
350: }
351: return(block(op, t, (int *)NULL, (union str *)NULL, p, TNULL));
352: }
353:
354: /*
355: * Traverse an expression tree, adjust things
356: * so the types of things in it are consistent
357: * with the view that its top node has
358: * type at.
359: * Used with structure references.
360: */
361: setype(p, t, newp)
362: register union tree *p, *newp;
363: register t;
364: {
365: for (;; p = p->t.tr1) {
366: p->t.subsp = newp->t.subsp;
367: p->t.strp = newp->t.strp;
368: p->t.type = t;
369: if (p->t.op==AMPER)
370: t = decref(t);
371: else if (p->t.op==STAR)
372: t = incref(t);
373: else if (p->t.op!=PLUS)
374: break;
375: }
376: }
377:
378: /*
379: * A mention of a function name is turned into
380: * a pointer to that function.
381: */
382: union tree *
383: chkfun(p)
384: register union tree *p;
385: {
386: register int t;
387:
388: if (((t = p->t.type)&XTYPE)==FUNC && p->t.op!=ETYPE)
389: return(block(AMPER,incref(t),p->t.subsp,p->t.strp,p,TNULL));
390: return(p);
391: }
392:
393: /*
394: * A mention of an array is turned into
395: * a pointer to the base of the array.
396: */
397: union tree *
398: disarray(p)
399: register union tree *p;
400: {
401: register int t;
402:
403: if (p==NULL)
404: return(p);
405: /* check array & not MOS and not typer */
406: if (((t = p->t.type)&XTYPE)!=ARRAY
407: || p->t.op==NAME && p->t.tr1->n.hclass==MOS
408: || p->t.op==ETYPE)
409: return(p);
410: p->t.subsp++;
411: *cp++ = p;
412: setype(p, decref(t), p);
413: build(AMPER);
414: return(*--cp);
415: }
416:
417: /*
418: * make sure that p is a ptr to a node
419: * with type int or char or 'okt.'
420: * okt might be nonexistent or 'long'
421: * (e.g. for <<).
422: */
423: chkw(p, okt)
424: union tree *p;
425: {
426: register int t;
427:
428: if ((t=p->t.type)!=INT && t<PTR && t!=CHAR && t!=UNCHAR && t!=UNSIGN && t!=okt)
429: error("Illegal type of operand");
430: return;
431: }
432:
433: /*
434: *'linearize' a type for looking up in the
435: * conversion table
436: */
437: lintyp(t)
438: {
439: switch(t) {
440:
441: case INT:
442: case CHAR:
443: case UNSIGN:
444: case UNCHAR:
445: return(0);
446:
447: case FLOAT:
448: case DOUBLE:
449: return(1);
450:
451: case LONG:
452: return(2);
453:
454: default:
455: return(3);
456: }
457: }
458:
459: /*
460: * Report an error.
461: */
462: /* VARARGS1 */
463: error(s, p1, p2, p3, p4, p5, p6)
464: char *s;
465: {
466: nerror++;
467: if (filename[0])
468: fprintf(stderr, "%s:", filename);
469: fprintf(stderr, "%d: ", line);
470: fprintf(stderr, s, p1, p2, p3, p4, p5, p6);
471: fprintf(stderr, "\n");
472: }
473:
474: /*
475: * Generate a node in an expression tree,
476: * setting the operator, type, dimen/struct table ptrs,
477: * and the operands.
478: */
479: union tree *
480: block(op, t, subs, str, p1,p2)
481: int *subs;
482: union str *str;
483: union tree *p1, *p2;
484: {
485: register union tree *p;
486:
487: p = (union tree *)Tblock(sizeof(struct tnode));
488: p->t.op = op;
489: p->t.type = t;
490: p->t.subsp = subs;
491: p->t.strp = str;
492: p->t.tr1 = p1;
493: if (opdope[op]&BINARY)
494: p->t.tr2 = p2;
495: else
496: p->t.tr2 = NULL;
497: return(p);
498: }
499:
500: union tree *
501: nblock(ds)
502: register struct nmlist *ds;
503: {
504: return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, (union tree *)ds, TNULL));
505: }
506:
507: /*
508: * Generate a block for a constant
509: */
510: union tree *
511: cblock(v)
512: {
513: register union tree *p;
514:
515: p = (union tree *)Tblock(sizeof(struct cnode));
516: p->c.op = CON;
517: p->c.type = INT;
518: p->c.subsp = NULL;
519: p->c.strp = NULL;
520: p->c.value = v;
521: return(p);
522: }
523:
524: /*
525: * A block for a float constant
526: */
527: union tree *
528: fblock(t, string)
529: char *string;
530: {
531: register union tree *p;
532:
533: p = (union tree *)Tblock(sizeof(struct fnode));
534: p->f.op = FCON;
535: p->f.type = t;
536: p->f.subsp = NULL;
537: p->f.strp = NULL;
538: p->f.cstr = string;
539: return(p);
540: }
541:
542: /*
543: * Assign a block for use in the
544: * expression tree.
545: */
546: char *
547: Tblock(n)
548: {
549: register char *p;
550:
551: p = treebase;
552: if (p==NULL) {
553: error("c0 internal error: tree not active");
554: exit(1);
555: }
556: if ((treebase += n) >= coremax) {
557: if (sbrk(1024) == (char *)-1) {
558: error("Out of space");
559: exit(1);
560: }
561: coremax += 1024;
562: }
563: return(p);
564: }
565:
566: char *
567: starttree()
568: {
569: register char *st;
570:
571: st = treebase;
572: if (st==NULL)
573: treebot = treebase = locbase+DCLSLOP;
574: return(st);
575: }
576:
577: endtree(tp)
578: char *tp;
579: {
580: treebase = tp;
581: if (tp==NULL)
582: treebot = NULL;
583: }
584:
585: /*
586: * Assign a block for use in a declaration
587: */
588: char *
589: Dblock(n)
590: {
591: register char *p;
592:
593: p = locbase;
594: locbase += n;
595: if (treebot && locbase > treebot) {
596: error("Too much declaring in an expression");
597: exit(1);
598: }
599: if (locbase > coremax) {
600: if (sbrk(1024) == (char *)-1) {
601: error("out of space");
602: exit(1);
603: }
604: coremax += 1024;
605: }
606: return(p);
607: }
608:
609: /*
610: * Check that a tree can be used as an lvalue.
611: */
612: chklval(p)
613: register union tree *p;
614: {
615: if (p->t.op==FSEL)
616: p = p->t.tr1;
617: if (p->t.op!=NAME && p->t.op!=STAR)
618: error("Lvalue required");
619: }
620:
621: /*
622: * reduce some forms of `constant op constant'
623: * to a constant. More of this is done in the next pass
624: * but this is used to allow constant expressions
625: * to be used in switches and array bounds.
626: */
627: fold(op, p1, p2)
628: register union tree *p1;
629: union tree *p2;
630: {
631: register int v1, v2;
632: int unsignf;
633:
634: if (p1->t.op!=CON)
635: return(0);
636: unsignf = p1->c.type==UNSIGN;
637: if (op==QUEST) {
638: if (p2->t.tr1->t.op==CON && p2->t.tr2->t.op==CON) {
639: p1->c.value = p1->c.value? p2->t.tr1->c.value: p2->t.tr2->c.value;
640: *cp++ = p1;
641: p1->t.type = p2->t.type;
642: return(1);
643: }
644: return(0);
645: }
646: if (p2) {
647: if (p2->t.op!=CON)
648: return(0);
649: v2 = p2->c.value;
650: unsignf |= p2->c.type==UNSIGN;
651: }
652: v1 = p1->c.value;
653: switch (op) {
654:
655: case PLUS:
656: v1 += v2;
657: break;
658:
659: case MINUS:
660: v1 -= v2;
661: break;
662:
663: case TIMES:
664: v1 *= v2;
665: break;
666:
667: case DIVIDE:
668: if (v2==0)
669: goto divchk;
670: if (unsignf) {
671: if (v2==1)
672: break;
673: if (v2<0) {
674: v1 = (unsigned)v1 >= (unsigned)v2;
675: break;
676: }
677: v1 = (unsigned)v1 / v2;
678: break;
679: }
680: v1 /= v2;
681: break;
682:
683: case MOD:
684: if (v2==0)
685: goto divchk;
686: if (unsignf) {
687: if (v2==1) {
688: v1 = 0;
689: break;
690: }
691: if (v2<0) {
692: if ((unsigned)v1 >= (unsigned)v2)
693: v1 -= v2;
694: break;
695: }
696: v1 = (unsigned)v1 % v2;
697: break;
698: }
699: v1 %= v2;
700: break;
701:
702: case AND:
703: v1 &= v2;
704: break;
705:
706: case OR:
707: v1 |= v2;
708: break;
709:
710: case EXOR:
711: v1 ^= v2;
712: break;
713:
714: case NEG:
715: v1 = - v1;
716: break;
717:
718: case COMPL:
719: v1 = ~ v1;
720: break;
721:
722: case LSHIFT:
723: v1 <<= v2;
724: break;
725:
726: case RSHIFT:
727: if (unsignf) {
728: v1 = (unsigned)v1 >> v2;
729: break;
730: }
731: v1 >>= v2;
732: break;
733:
734: case EQUAL:
735: v1 = v1==v2;
736: break;
737:
738: case NEQUAL:
739: v1 = v1!=v2;
740: break;
741:
742: case LESS:
743: v1 = v1<v2;
744: break;
745:
746: case GREAT:
747: v1 = v1>v2;
748: break;
749:
750: case LESSEQ:
751: v1 = v1<=v2;
752: break;
753:
754: case GREATEQ:
755: v1 = v1>=v2;
756: break;
757:
758: divchk:
759: error("Divide check");
760: nerror--;
761: default:
762: return(0);
763: }
764: p1->c.value = v1;
765: *cp++ = p1;
766: if (unsignf)
767: p1->t.type = UNSIGN;
768: return(1);
769: }
770:
771: /*
772: * Compile an expression expected to have constant value,
773: * for example an array bound or a case value.
774: */
775: conexp()
776: {
777: register union tree *t;
778:
779: initflg++;
780: if (t = tree(1))
781: if (t->t.op != CON)
782: error("Constant required");
783: initflg--;
784: return(t->c.value);
785: }
786:
787: /*
788: * Handle peculiar assignment ops that need a temporary.
789: */
790: assignop(op, p1, p2)
791: register union tree *p1, *p2;
792: {
793: register struct nmlist *np;
794:
795: op += PLUS - ASPLUS;
796: if (p1->t.op==NAME) {
797: *cp++ = p1;
798: *cp++ = p1;
799: *cp++ = p2;
800: build(op);
801: build(ASSIGN);
802: return;
803: }
804: np = gentemp(incref(p1->t.type));
805: *cp++ = nblock(np);
806: *cp++ = p1;
807: build(AMPER);
808: build(ASSIGN);
809: *cp++ = nblock(np);
810: build(STAR);
811: *cp++ = nblock(np);
812: build(STAR);
813: *cp++ = p2;
814: build(op);
815: build(ASSIGN);
816: build(SEQNC);
817: }
818:
819: /*
820: * Generate an automatic temporary for
821: * use in certain assignment ops
822: */
823: struct nmlist *
824: gentemp(type)
825: {
826: register struct nmlist *tp;
827:
828: tp = (struct nmlist *)Tblock(sizeof(struct nmlist));
829: tp->hclass = AUTO;
830: tp->htype = type;
831: tp->hflag = 0;
832: tp->hsubsp = NULL;
833: tp->hstrp = NULL;
834: tp->hblklev = blklev;
835: autolen -= rlength((union tree *)tp);
836: tp->hoffset = autolen;
837: if (autolen < maxauto)
838: maxauto = autolen;
839: return(tp);
840: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.