|
|
1.1 root 1: static char *sccsid ="%W% (Berkeley) %G%";
2: # include "mfile1"
3:
4: /* corrections when in violation of lint */
5:
6: /* some special actions, used in finding the type of nodes */
7: # define NCVT 01
8: # define PUN 02
9: # define TYPL 04
10: # define TYPR 010
11: # define TYMATCH 040
12: # define LVAL 0100
13: # define CVTO 0200
14: # define CVTL 0400
15: # define CVTR 01000
16: # define PTMATCH 02000
17: # define OTHER 04000
18: # define NCVTR 010000
19:
20: /* node conventions:
21:
22: NAME: rval>0 is stab index for external
23: rval<0 is -inlabel number
24: lval is offset in bits
25: ICON: lval has the value
26: rval has the STAB index, or - label number,
27: if a name whose address is in the constant
28: rval = NONAME means no name
29: REG: rval is reg. identification cookie
30:
31: */
32:
33: int bdebug = 0;
34: extern ddebug;
35:
36: NODE *
37: buildtree( o, l, r ) register NODE *l, *r; {
38: register NODE *p, *q;
39: register actions;
40: register opty;
41: register struct symtab *sp;
42: register NODE *lr, *ll;
43: int i;
44: extern int eprint();
45:
46: # ifndef BUG1
47: if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
48: # endif
49: opty = optype(o);
50:
51: /* check for constants */
52:
53: if( opty == UTYPE && l->in.op == ICON ){
54:
55: switch( o ){
56:
57: case NOT:
58: if( hflag ) werror( "constant argument to NOT" );
59: case UNARY MINUS:
60: case COMPL:
61: if( conval( l, o, l ) ) return(l);
62: break;
63:
64: }
65: }
66:
67: else if( o==UNARY MINUS && l->in.op==FCON ){
68: l->fpn.dval = -l->fpn.dval;
69: return(l);
70: }
71:
72: else if( o==QUEST && l->in.op==ICON ) {
73: l->in.op = FREE;
74: r->in.op = FREE;
75: if( l->tn.lval ){
76: tfree( r->in.right );
77: return( r->in.left );
78: }
79: else {
80: tfree( r->in.left );
81: return( r->in.right );
82: }
83: }
84:
85: else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
86:
87: else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
88:
89: switch( o ){
90:
91: case ULT:
92: case UGT:
93: case ULE:
94: case UGE:
95: case LT:
96: case GT:
97: case LE:
98: case GE:
99: case EQ:
100: case NE:
101: case ANDAND:
102: case OROR:
103: case CBRANCH:
104:
105: ccwarn:
106: if( hflag ) werror( "constant in conditional context" );
107:
108: case PLUS:
109: case MINUS:
110: case MUL:
111: case DIV:
112: case MOD:
113: case AND:
114: case OR:
115: case ER:
116: case LS:
117: case RS:
118: if( conval( l, o, r ) ) {
119: r->in.op = FREE;
120: return(l);
121: }
122: break;
123: }
124: }
125:
126: else if( opty == BITYPE && (l->in.op==FCON||l->in.op==ICON) &&
127: (r->in.op==FCON||r->in.op==ICON) ){
128: switch(o){
129: case PLUS:
130: case MINUS:
131: case MUL:
132: case DIV:
133: if( l->in.op == ICON ){
134: l->fpn.dval = l->tn.lval;
135: }
136: if( r->in.op == ICON ){
137: r->fpn.dval = r->tn.lval;
138: }
139: l->in.op = FCON;
140: l->in.type = l->fn.csiz = DOUBLE;
141: r->in.op = FREE;
142: switch(o){
143: case PLUS:
144: l->fpn.dval += r->fpn.dval;
145: return(l);
146: case MINUS:
147: l->fpn.dval -= r->fpn.dval;
148: return(l);
149: case MUL:
150: l->fpn.dval *= r->fpn.dval;
151: return(l);
152: case DIV:
153: if( r->fpn.dval == 0 ) uerror( "division by 0." );
154: else l->fpn.dval /= r->fpn.dval;
155: return(l);
156: }
157: }
158: }
159:
160: /* its real; we must make a new node */
161:
162: p = block( o, l, r, INT, 0, INT );
163:
164: actions = opact(p);
165:
166: if( actions&LVAL ){ /* check left descendent */
167: if( notlval(p->in.left) ) {
168: uerror( "illegal lhs of assignment operator" );
169: }
170: }
171:
172: if( actions & NCVTR ){
173: p->in.left = pconvert( p->in.left );
174: }
175: else if( !(actions & NCVT ) ){
176: switch( opty ){
177:
178: case BITYPE:
179: p->in.right = pconvert( p->in.right );
180: case UTYPE:
181: p->in.left = pconvert( p->in.left );
182:
183: }
184: }
185:
186: if( (actions&PUN) && (o!=CAST||cflag) ){
187: chkpun(p);
188: }
189:
190: if( actions & (TYPL|TYPR) ){
191:
192: q = (actions&TYPL) ? p->in.left : p->in.right;
193:
194: p->in.type = q->in.type;
195: p->fn.cdim = q->fn.cdim;
196: p->fn.csiz = q->fn.csiz;
197: }
198:
199: if( actions & CVTL ) p = convert( p, CVTL );
200: if( actions & CVTR ) p = convert( p, CVTR );
201: if( actions & TYMATCH ) p = tymatch(p);
202: if( actions & PTMATCH ) p = ptmatch(p);
203:
204: if( actions & OTHER ){
205: l = p->in.left;
206: r = p->in.right;
207:
208: switch(o){
209:
210: case NAME:
211: sp = &stab[idname];
212: if( sp->stype == UNDEF ){
213: #ifndef FLEXNAMES
214: uerror( "%.8s undefined", sp->sname );
215: #else
216: uerror( "%s undefined", sp->sname );
217: #endif
218: /* make p look reasonable */
219: p->in.type = p->fn.cdim = p->fn.csiz = INT;
220: p->tn.rval = idname;
221: p->tn.lval = 0;
222: defid( p, SNULL );
223: break;
224: }
225: p->in.type = sp->stype;
226: p->fn.cdim = sp->dimoff;
227: p->fn.csiz = sp->sizoff;
228: p->tn.lval = 0;
229: p->tn.rval = idname;
230: /* special case: MOETY is really an ICON... */
231: if( p->in.type == MOETY ){
232: p->tn.rval = NONAME;
233: p->tn.lval = sp->offset;
234: p->fn.cdim = 0;
235: p->in.type = ENUMTY;
236: p->in.op = ICON;
237: }
238: break;
239:
240: case ICON:
241: p->in.type = INT;
242: p->fn.cdim = 0;
243: p->fn.csiz = INT;
244: break;
245:
246: case STRING:
247: p->in.op = NAME;
248: p->in.type = CHAR+ARY;
249: p->tn.lval = 0;
250: p->tn.rval = NOLAB;
251: p->fn.cdim = curdim;
252: p->fn.csiz = CHAR;
253: break;
254:
255: case FCON:
256: p->tn.lval = 0;
257: p->tn.rval = 0;
258: p->in.type = DOUBLE;
259: p->fn.cdim = 0;
260: p->fn.csiz = DOUBLE;
261: break;
262:
263: case STREF:
264: /* p->x turned into *(p+offset) */
265: /* rhs must be a name; check correctness */
266:
267: i = r->tn.rval;
268: if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
269: uerror( "member of structure or union required" );
270: }else
271: /* if this name is non-unique, find right one */
272: if( stab[i].sflags & SNONUNIQ &&
273: (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
274: (l->fn.csiz +1) >= 0 ){
275: /* nonunique name && structure defined */
276: char * memnam, * tabnam;
277: register k;
278: int j;
279: int memi;
280: j=dimtab[l->fn.csiz+1];
281: for( ; (memi=dimtab[j]) >= 0; ++j ){
282: tabnam = stab[memi].sname;
283: memnam = stab[i].sname;
284: # ifndef BUG1
285: if( ddebug>1 ){
286: #ifndef FLEXNAMES
287: printf("member %.8s==%.8s?\n",
288: #else
289: printf("member %s==%s?\n",
290: #endif
291: memnam, tabnam);
292: }
293: # endif
294: if( stab[memi].sflags & SNONUNIQ ){
295: #ifndef FLEXNAMES
296: for( k=0; k<NCHNAM; ++k ){
297: if(*memnam++!=*tabnam)
298: goto next;
299: if(!*tabnam++) break;
300: }
301: #else
302: if (memnam != tabnam)
303: goto next;
304: #endif
305: r->tn.rval = i = memi;
306: break;
307: }
308: next: continue;
309: }
310: if( memi < 0 )
311: #ifndef FLEXNAMES
312: uerror("illegal member use: %.8s",
313: #else
314: uerror("illegal member use: %s",
315: #endif
316: stab[i].sname);
317: }
318: else {
319: register j;
320: if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
321: if( stab[i].sflags & SNONUNIQ ){
322: uerror( "nonunique name demands struct/union or struct/union pointer" );
323: }
324: else werror( "struct/union or struct/union pointer required" );
325: }
326: else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
327: else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
328: #ifndef FLEXNAMES
329: werror( "illegal member use: %.8s", stab[i].sname );
330: #else
331: werror( "illegal member use: %s", stab[i].sname );
332: #endif
333: }
334: }
335:
336: p = stref( p );
337: break;
338:
339: case UNARY MUL:
340: if( l->in.op == UNARY AND ){
341: p->in.op = l->in.op = FREE;
342: p = l->in.left;
343: }
344: if( !ISPTR(l->in.type))uerror("illegal indirection");
345: p->in.type = DECREF(l->in.type);
346: p->fn.cdim = l->fn.cdim;
347: p->fn.csiz = l->fn.csiz;
348: break;
349:
350: case UNARY AND:
351: switch( l->in.op ){
352:
353: case UNARY MUL:
354: p->in.op = l->in.op = FREE;
355: p = l->in.left;
356: case NAME:
357: p->in.type = INCREF( l->in.type );
358: p->fn.cdim = l->fn.cdim;
359: p->fn.csiz = l->fn.csiz;
360: break;
361:
362: case COMOP:
363: lr = buildtree( UNARY AND, l->in.right, NIL );
364: p->in.op = l->in.op = FREE;
365: p = buildtree( COMOP, l->in.left, lr );
366: break;
367:
368: case QUEST:
369: lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
370: ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
371: p->in.op = l->in.op = l->in.right->in.op = FREE;
372: p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
373: break;
374:
375: # ifdef ADDROREG
376: case OREG:
377: /* OREG was built in clocal()
378: * for an auto or formal parameter
379: * now its address is being taken
380: * local code must unwind it
381: * back to PLUS/MINUS REG ICON
382: * according to local conventions
383: */
384: {
385: extern NODE * addroreg();
386: p->in.op = FREE;
387: p = addroreg( l );
388: }
389: break;
390:
391: # endif
392: default:
393: uerror( "unacceptable operand of &" );
394: break;
395: }
396: break;
397:
398: case LS:
399: case RS:
400: case ASG LS:
401: case ASG RS:
402: if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
403: p->in.right = makety(p->in.right, INT, 0, INT );
404: break;
405:
406: case RETURN:
407: case ASSIGN:
408: case CAST:
409: /* structure assignment */
410: /* take the addresses of the two sides; then make an
411: /* operator using STASG and
412: /* the addresses of left and right */
413:
414: {
415: register TWORD t;
416: register d, s;
417:
418: if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
419:
420: r = buildtree( UNARY AND, r, NIL );
421: t = r->in.type;
422: d = r->fn.cdim;
423: s = r->fn.csiz;
424:
425: l = block( STASG, l, r, t, d, s );
426:
427: if( o == RETURN ){
428: p->in.op = FREE;
429: p = l;
430: break;
431: }
432:
433: p->in.op = UNARY MUL;
434: p->in.left = l;
435: p->in.right = NIL;
436: break;
437: }
438: case COLON:
439: /* structure colon */
440:
441: if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
442: break;
443:
444: case CALL:
445: p->in.right = r = strargs( p->in.right );
446: case UNARY CALL:
447: if( !ISPTR(l->in.type)) uerror("illegal function");
448: p->in.type = DECREF(l->in.type);
449: if( !ISFTN(p->in.type)) uerror("illegal function");
450: p->in.type = DECREF( p->in.type );
451: p->fn.cdim = l->fn.cdim;
452: p->fn.csiz = l->fn.csiz;
453: if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
454: l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
455: ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
456: p->in.op += (FORTCALL-CALL);
457: }
458: if( p->in.type == STRTY || p->in.type == UNIONTY ){
459: /* function returning structure */
460: /* make function really return ptr to str., with * */
461:
462: p->in.op += STCALL-CALL;
463: p->in.type = INCREF( p->in.type );
464: p = buildtree( UNARY MUL, p, NIL );
465:
466: }
467: break;
468:
469: default:
470: cerror( "other code %d", o );
471: }
472:
473: }
474:
475: if( actions & CVTO ) p = oconvert(p);
476: p = clocal(p);
477:
478: # ifndef BUG1
479: if( bdebug ) fwalk( p, eprint, 0 );
480: # endif
481:
482: return(p);
483:
484: }
485:
486: NODE *
487: strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */
488:
489: if( p->in.op == CM ){
490: p->in.left = strargs( p->in.left );
491: p->in.right = strargs( p->in.right );
492: return( p );
493: }
494:
495: if( p->in.type == STRTY || p->in.type == UNIONTY ){
496: p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
497: p->in.left = buildtree( UNARY AND, p->in.left, NIL );
498: p = clocal(p);
499: }
500: return( p );
501: }
502:
503: chkstr( i, j, type ) TWORD type; {
504: /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
505: /* i has been checked to contain a MOS or MOU */
506: /* j is the index in dimtab of the members... */
507: int k, kk;
508:
509: extern int ddebug;
510:
511: # ifndef BUG1
512: #ifndef FLEXNAMES
513: if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
514: #else
515: if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
516: #endif
517: # endif
518: if( (k = j) < 0 ) uerror( "undefined structure or union" );
519: else {
520: for( ; (kk = dimtab[k] ) >= 0; ++k ){
521: if( kk >= SYMTSZ ){
522: cerror( "gummy structure" );
523: return(1);
524: }
525: if( kk == i ) return( 1 );
526: switch( stab[kk].stype ){
527:
528: case STRTY:
529: case UNIONTY:
530: if( type == STRTY ) continue; /* no recursive looking for strs */
531: if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
532: if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */
533: werror(
534: #ifndef FLEXNAMES
535: "illegal member use: perhaps %.8s.%.8s?",
536: #else
537: "illegal member use: perhaps %s.%s?",
538: #endif
539: stab[kk].sname, stab[i].sname );
540: return(1);
541: }
542: }
543: }
544: }
545: return( 0 );
546: }
547:
548: conval( p, o, q ) register NODE *p, *q; {
549: /* apply the op o to the lval part of p; if binary, rhs is val */
550: int i, u;
551: CONSZ val;
552:
553: val = q->tn.lval;
554: u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
555: if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
556:
557: if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
558: if( q->tn.rval != NONAME && o!=PLUS ) return(0);
559: if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
560:
561: switch( o ){
562:
563: case PLUS:
564: p->tn.lval += val;
565: if( p->tn.rval == NONAME ){
566: p->tn.rval = q->tn.rval;
567: p->in.type = q->in.type;
568: }
569: break;
570: case MINUS:
571: p->tn.lval -= val;
572: break;
573: case MUL:
574: p->tn.lval *= val;
575: break;
576: case DIV:
577: if( val == 0 ) uerror( "division by 0" );
578: else p->tn.lval /= val;
579: break;
580: case MOD:
581: if( val == 0 ) uerror( "division by 0" );
582: else p->tn.lval %= val;
583: break;
584: case AND:
585: p->tn.lval &= val;
586: break;
587: case OR:
588: p->tn.lval |= val;
589: break;
590: case ER:
591: p->tn.lval ^= val;
592: break;
593: case LS:
594: i = val;
595: p->tn.lval = p->tn.lval << i;
596: break;
597: case RS:
598: i = val;
599: p->tn.lval = p->tn.lval >> i;
600: break;
601:
602: case UNARY MINUS:
603: p->tn.lval = - p->tn.lval;
604: break;
605: case COMPL:
606: p->tn.lval = ~p->tn.lval;
607: break;
608: case NOT:
609: p->tn.lval = !p->tn.lval;
610: break;
611: case LT:
612: p->tn.lval = p->tn.lval < val;
613: break;
614: case LE:
615: p->tn.lval = p->tn.lval <= val;
616: break;
617: case GT:
618: p->tn.lval = p->tn.lval > val;
619: break;
620: case GE:
621: p->tn.lval = p->tn.lval >= val;
622: break;
623: case ULT:
624: p->tn.lval = (p->tn.lval-val)<0;
625: break;
626: case ULE:
627: p->tn.lval = (p->tn.lval-val)<=0;
628: break;
629: case UGE:
630: p->tn.lval = (p->tn.lval-val)>=0;
631: break;
632: case UGT:
633: p->tn.lval = (p->tn.lval-val)>0;
634: break;
635: case EQ:
636: p->tn.lval = p->tn.lval == val;
637: break;
638: case NE:
639: p->tn.lval = p->tn.lval != val;
640: break;
641: default:
642: return(0);
643: }
644: return(1);
645: }
646:
647: chkpun(p) register NODE *p; {
648:
649: /* checks p for the existance of a pun */
650:
651: /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
652:
653: /* one case is when enumerations are used: this applies only to lint */
654: /* in the other case, one operand is a pointer, the other integer type */
655: /* we check that this integer is in fact a constant zero... */
656:
657: /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
658: /* this falls out, because the LHS is never 0 */
659:
660: register NODE *q;
661: register t1, t2;
662: register d1, d2;
663:
664: t1 = p->in.left->in.type;
665: t2 = p->in.right->in.type;
666:
667: if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
668: if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
669: uerror( "illegal comparison of enums" );
670: return;
671: }
672: if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
673: werror( "enumeration type clash, operator %s", opst[p->in.op] );
674: return;
675: }
676:
677: if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
678: else q = p->in.left;
679:
680: if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
681: if( q->in.op != ICON || q->tn.lval != 0 ){
682: werror( "illegal combination of pointer and integer, op %s",
683: opst[p->in.op] );
684: }
685: }
686: else {
687: d1 = p->in.left->fn.cdim;
688: d2 = p->in.right->fn.cdim;
689: for( ;; ){
690: if( t1 == t2 ) {;
691: if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
692: werror( "illegal structure pointer combination" );
693: }
694: return;
695: }
696: if( ISARY(t1) || ISPTR(t1) ){
697: if( !ISARY(t2) && !ISPTR(t2) ) break;
698: if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
699: werror( "illegal array size combination" );
700: return;
701: }
702: if( ISARY(t1) ) ++d1;
703: if( ISARY(t2) ) ++d2;
704: }
705: else break;
706: t1 = DECREF(t1);
707: t2 = DECREF(t2);
708: }
709: werror( "illegal pointer combination" );
710: }
711:
712: }
713:
714: NODE *
715: stref( p ) register NODE *p; {
716:
717: TWORD t;
718: int d, s, dsc, align;
719: OFFSZ off;
720: register struct symtab *q;
721:
722: /* make p->x */
723: /* this is also used to reference automatic variables */
724:
725: q = &stab[p->in.right->tn.rval];
726: p->in.right->in.op = FREE;
727: p->in.op = FREE;
728: p = pconvert( p->in.left );
729:
730: /* make p look like ptr to x */
731:
732: if( !ISPTR(p->in.type)){
733: p->in.type = PTR+UNIONTY;
734: }
735:
736: t = INCREF( q->stype );
737: d = q->dimoff;
738: s = q->sizoff;
739:
740: p = makety( p, t, d, s );
741:
742: /* compute the offset to be added */
743:
744: off = q->offset;
745: dsc = q->sclass;
746:
747: if( dsc & FIELD ) { /* normalize offset */
748: align = ALINT;
749: s = INT;
750: off = (off/align)*align;
751: }
752: if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
753:
754: p = buildtree( UNARY MUL, p, NIL );
755:
756: /* if field, build field info */
757:
758: if( dsc & FIELD ){
759: p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
760: p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
761: }
762:
763: return( clocal(p) );
764: }
765:
766: notlval(p) register NODE *p; {
767:
768: /* return 0 if p an lvalue, 1 otherwise */
769:
770: again:
771:
772: switch( p->in.op ){
773:
774: case FLD:
775: p = p->in.left;
776: goto again;
777:
778: case UNARY MUL:
779: /* fix the &(a=b) bug, given that a and b are structures */
780: if( p->in.left->in.op == STASG ) return( 1 );
781: /* and the f().a bug, given that f returns a structure */
782: if( p->in.left->in.op == UNARY STCALL ||
783: p->in.left->in.op == STCALL ) return( 1 );
784: case NAME:
785: case OREG:
786: if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
787: case REG:
788: return(0);
789:
790: default:
791: return(1);
792:
793: }
794:
795: }
796:
797: NODE *
798: bcon( i ){ /* make a constant node with value i */
799: register NODE *p;
800:
801: p = block( ICON, NIL, NIL, INT, 0, INT );
802: p->tn.lval = i;
803: p->tn.rval = NONAME;
804: return( clocal(p) );
805: }
806:
807: NODE *
808: bpsize(p) register NODE *p; {
809: return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
810: }
811:
812: OFFSZ
813: psize( p ) NODE *p; {
814: /* p is a node of type pointer; psize returns the
815: size of the thing pointed to */
816:
817: if( !ISPTR(p->in.type) ){
818: uerror( "pointer required");
819: return( SZINT );
820: }
821: /* note: no pointers to fields */
822: return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
823: }
824:
825: NODE *
826: convert( p, f ) register NODE *p; {
827: /* convert an operand of p
828: f is either CVTL or CVTR
829: operand has type int, and is converted by the size of the other side
830: */
831:
832: register NODE *q, *r;
833:
834: q = (f==CVTL)?p->in.left:p->in.right;
835:
836: r = block( PMCONV,
837: q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
838: r = clocal(r);
839: if( f == CVTL )
840: p->in.left = r;
841: else
842: p->in.right = r;
843: return(p);
844:
845: }
846:
847: econvert( p ) register NODE *p; {
848:
849: /* change enums to ints, or appropriate types */
850:
851: register TWORD ty;
852:
853: if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
854: if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
855: else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
856: else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
857: else ty = LONG;
858: ty = ctype( ty );
859: p->fn.csiz = ty;
860: MODTYPE(p->in.type,ty);
861: if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
862: }
863: }
864:
865: NODE *
866: pconvert( p ) register NODE *p; {
867:
868: /* if p should be changed into a pointer, do so */
869:
870: if( ISARY( p->in.type) ){
871: p->in.type = DECREF( p->in.type );
872: ++p->fn.cdim;
873: return( buildtree( UNARY AND, p, NIL ) );
874: }
875: if( ISFTN( p->in.type) )
876: return( buildtree( UNARY AND, p, NIL ) );
877:
878: return( p );
879: }
880:
881: NODE *
882: oconvert(p) register NODE *p; {
883: /* convert the result itself: used for pointer and unsigned */
884:
885: switch(p->in.op) {
886:
887: case LE:
888: case LT:
889: case GE:
890: case GT:
891: if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE);
892: case EQ:
893: case NE:
894: return( p );
895:
896: case MINUS:
897: return( clocal( block( PVCONV,
898: p, bpsize(p->in.left), INT, 0, INT ) ) );
899: }
900:
901: cerror( "illegal oconvert: %d", p->in.op );
902:
903: return(p);
904: }
905:
906: NODE *
907: ptmatch(p) register NODE *p; {
908:
909: /* makes the operands of p agree; they are
910: either pointers or integers, by this time */
911: /* with MINUS, the sizes must be the same */
912: /* with COLON, the types must be the same */
913:
914: TWORD t1, t2, t;
915: int o, d2, d, s2, s;
916:
917: o = p->in.op;
918: t = t1 = p->in.left->in.type;
919: t2 = p->in.right->in.type;
920: d = p->in.left->fn.cdim;
921: d2 = p->in.right->fn.cdim;
922: s = p->in.left->fn.csiz;
923: s2 = p->in.right->fn.csiz;
924:
925: switch( o ){
926:
927: case ASSIGN:
928: case RETURN:
929: case CAST:
930: { break; }
931:
932: case MINUS:
933: { if( psize(p->in.left) != psize(p->in.right) ){
934: uerror( "illegal pointer subtraction");
935: }
936: break;
937: }
938: case COLON:
939: { if( t1 != t2 ) uerror( "illegal types in :");
940: break;
941: }
942: default: /* must work harder: relationals or comparisons */
943:
944: if( !ISPTR(t1) ){
945: t = t2;
946: d = d2;
947: s = s2;
948: break;
949: }
950: if( !ISPTR(t2) ){
951: break;
952: }
953:
954: /* both are pointers */
955: if( talign(t2,s2) < talign(t,s) ){
956: t = t2;
957: s = s2;
958: }
959: break;
960: }
961:
962: p->in.left = makety( p->in.left, t, d, s );
963: p->in.right = makety( p->in.right, t, d, s );
964: if( o!=MINUS && !logop(o) ){
965:
966: p->in.type = t;
967: p->fn.cdim = d;
968: p->fn.csiz = s;
969: }
970:
971: return(clocal(p));
972: }
973:
974: int tdebug = 0;
975:
976: NODE *
977: tymatch(p) register NODE *p; {
978:
979: /* satisfy the types of various arithmetic binary ops */
980:
981: /* rules are:
982: if assignment, op, type of LHS
983: if any float or doubles, make double
984: if any longs, make long
985: otherwise, make int
986: if either operand is unsigned, the result is...
987: */
988:
989: register TWORD t1, t2, t, tu;
990: register o, u;
991:
992: o = p->in.op;
993:
994: t1 = p->in.left->in.type;
995: t2 = p->in.right->in.type;
996: if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
997: uerror("void type illegal in expression");
998:
999: u = 0;
1000: if( ISUNSIGNED(t1) ){
1001: u = 1;
1002: t1 = DEUNSIGN(t1);
1003: }
1004: if( ISUNSIGNED(t2) ){
1005: u = 1;
1006: t2 = DEUNSIGN(t2);
1007: }
1008:
1009: if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
1010: if( t2 == CHAR || t2 == SHORT ) t2 = INT;
1011:
1012: if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE;
1013: else if( t1==LONG || t2==LONG ) t = LONG;
1014: else t = INT;
1015:
1016: if( asgop(o) ){
1017: tu = p->in.left->in.type;
1018: t = t1;
1019: }
1020: else {
1021: tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1022: }
1023:
1024: /* because expressions have values that are at least as wide
1025: as INT or UNSIGNED, the only conversions needed
1026: are those involving FLOAT/DOUBLE, and those
1027: from LONG to INT and ULONG to UNSIGNED */
1028:
1029: if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu );
1030:
1031: if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu );
1032:
1033: if( asgop(o) ){
1034: p->in.type = p->in.left->in.type;
1035: p->fn.cdim = p->in.left->fn.cdim;
1036: p->fn.csiz = p->in.left->fn.csiz;
1037: }
1038: else if( !logop(o) ){
1039: p->in.type = tu;
1040: p->fn.cdim = 0;
1041: p->fn.csiz = t;
1042: }
1043:
1044: # ifndef BUG1
1045: if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
1046: # endif
1047:
1048: return(p);
1049: }
1050:
1051: NODE *
1052: makety( p, t, d, s ) register NODE *p; TWORD t; {
1053: /* make p into type t by inserting a conversion */
1054:
1055: if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
1056: if( t == p->in.type ){
1057: p->fn.cdim = d;
1058: p->fn.csiz = s;
1059: return( p );
1060: }
1061:
1062: if( t & TMASK ){
1063: /* non-simple type */
1064: return( block( PCONV, p, NIL, t, d, s ) );
1065: }
1066:
1067: if( p->in.op == ICON ){
1068: if( t==DOUBLE||t==FLOAT ){
1069: p->in.op = FCON;
1070: if( ISUNSIGNED(p->in.type) ){
1071: p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
1072: }
1073: else {
1074: p->fpn.dval = p->tn.lval;
1075: }
1076:
1077: p->in.type = p->fn.csiz = t;
1078: return( clocal(p) );
1079: }
1080: }
1081:
1082: return( block( SCONV, p, NIL, t, d, s ) );
1083:
1084: }
1085:
1086: NODE *
1087: block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
1088:
1089: register NODE *p;
1090:
1091: p = talloc();
1092: p->in.op = o;
1093: p->in.left = l;
1094: p->in.right = r;
1095: p->in.type = t;
1096: p->fn.cdim = d;
1097: p->fn.csiz = s;
1098: return(p);
1099: }
1100:
1101: icons(p) register NODE *p; {
1102: /* if p is an integer constant, return its value */
1103: int val;
1104:
1105: if( p->in.op != ICON ){
1106: uerror( "constant expected");
1107: val = 1;
1108: }
1109: else {
1110: val = p->tn.lval;
1111: if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
1112: }
1113: tfree( p );
1114: return(val);
1115: }
1116:
1117: /* the intent of this table is to examine the
1118: operators, and to check them for
1119: correctness.
1120:
1121: The table is searched for the op and the
1122: modified type (where this is one of the
1123: types INT (includes char and short), LONG,
1124: DOUBLE (includes FLOAT), and POINTER
1125:
1126: The default action is to make the node type integer
1127:
1128: The actions taken include:
1129: PUN check for puns
1130: CVTL convert the left operand
1131: CVTR convert the right operand
1132: TYPL the type is determined by the left operand
1133: TYPR the type is determined by the right operand
1134: TYMATCH force type of left and right to match, by inserting conversions
1135: PTMATCH like TYMATCH, but for pointers
1136: LVAL left operand must be lval
1137: CVTO convert the op
1138: NCVT do not convert the operands
1139: OTHER handled by code
1140: NCVTR convert the left operand, not the right...
1141:
1142: */
1143:
1144: # define MINT 01 /* integer */
1145: # define MDBI 02 /* integer or double */
1146: # define MSTR 04 /* structure */
1147: # define MPTR 010 /* pointer */
1148: # define MPTI 020 /* pointer or integer */
1149: # define MENU 040 /* enumeration variable or member */
1150:
1151: opact( p ) NODE *p; {
1152:
1153: register mt12, mt1, mt2, o;
1154:
1155: mt12 = 0;
1156:
1157: switch( optype(o=p->in.op) ){
1158:
1159: case BITYPE:
1160: mt12=mt2 = moditype( p->in.right->in.type );
1161: case UTYPE:
1162: mt12 &= (mt1 = moditype( p->in.left->in.type ));
1163:
1164: }
1165:
1166: switch( o ){
1167:
1168: case NAME :
1169: case STRING :
1170: case ICON :
1171: case FCON :
1172: case CALL :
1173: case UNARY CALL:
1174: case UNARY MUL:
1175: { return( OTHER ); }
1176: case UNARY MINUS:
1177: if( mt1 & MDBI ) return( TYPL );
1178: break;
1179:
1180: case COMPL:
1181: if( mt1 & MINT ) return( TYPL );
1182: break;
1183:
1184: case UNARY AND:
1185: { return( NCVT+OTHER ); }
1186: case INIT:
1187: case CM:
1188: case NOT:
1189: case CBRANCH:
1190: case ANDAND:
1191: case OROR:
1192: return( 0 );
1193:
1194: case MUL:
1195: case DIV:
1196: if( mt12 & MDBI ) return( TYMATCH );
1197: break;
1198:
1199: case MOD:
1200: case AND:
1201: case OR:
1202: case ER:
1203: if( mt12 & MINT ) return( TYMATCH );
1204: break;
1205:
1206: case LS:
1207: case RS:
1208: if( mt12 & MINT ) return( TYMATCH+OTHER );
1209: break;
1210:
1211: case EQ:
1212: case NE:
1213: case LT:
1214: case LE:
1215: case GT:
1216: case GE:
1217: if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
1218: if( mt12 & MDBI ) return( TYMATCH+CVTO );
1219: else if( mt12 & MPTR ) return( PTMATCH+PUN );
1220: else if( mt12 & MPTI ) return( PTMATCH+PUN );
1221: else break;
1222:
1223: case QUEST:
1224: case COMOP:
1225: if( mt2&MENU ) return( TYPR+NCVTR );
1226: return( TYPR );
1227:
1228: case STREF:
1229: return( NCVTR+OTHER );
1230:
1231: case FORCE:
1232: return( TYPL );
1233:
1234: case COLON:
1235: if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
1236: else if( mt12 & MDBI ) return( TYMATCH );
1237: else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1238: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1239: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1240: else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1241: break;
1242:
1243: case ASSIGN:
1244: case RETURN:
1245: if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1246: case CAST:
1247: if(o==CAST && mt1==0)return(TYPL+TYMATCH);
1248: if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
1249: else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
1250: else if( mt12 == 0 ) break;
1251: else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
1252: else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1253: break;
1254:
1255: case ASG LS:
1256: case ASG RS:
1257: if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1258: break;
1259:
1260: case ASG MUL:
1261: case ASG DIV:
1262: if( mt12 & MDBI ) return( LVAL+TYMATCH );
1263: break;
1264:
1265: case ASG MOD:
1266: case ASG AND:
1267: case ASG OR:
1268: case ASG ER:
1269: if( mt12 & MINT ) return( LVAL+TYMATCH );
1270: break;
1271:
1272: case ASG PLUS:
1273: case ASG MINUS:
1274: case INCR:
1275: case DECR:
1276: if( mt12 & MDBI ) return( TYMATCH+LVAL );
1277: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1278: break;
1279:
1280: case MINUS:
1281: if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1282: if( mt2 & MPTR ) break;
1283: case PLUS:
1284: if( mt12 & MDBI ) return( TYMATCH );
1285: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1286: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1287:
1288: }
1289: uerror( "operands of %s have incompatible types", opst[o] );
1290: return( NCVT );
1291: }
1292:
1293: moditype( ty ) TWORD ty; {
1294:
1295: switch( ty ){
1296:
1297: case TVOID:
1298: case UNDEF:
1299: return(0); /* type is void */
1300: case ENUMTY:
1301: case MOETY:
1302: return( MENU );
1303:
1304: case STRTY:
1305: case UNIONTY:
1306: return( MSTR );
1307:
1308: case CHAR:
1309: case SHORT:
1310: case UCHAR:
1311: case USHORT:
1312: return( MINT|MPTI|MDBI );
1313: case UNSIGNED:
1314: case ULONG:
1315: case INT:
1316: case LONG:
1317: return( MINT|MDBI|MPTI );
1318: case FLOAT:
1319: case DOUBLE:
1320: return( MDBI );
1321: default:
1322: return( MPTR|MPTI );
1323:
1324: }
1325: }
1326:
1327: NODE *
1328: doszof( p ) register NODE *p; {
1329: /* do sizeof p */
1330: int i;
1331:
1332: /* whatever is the meaning of this if it is a bitfield? */
1333: i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1334:
1335: tfree(p);
1336: if( i <= 0 ) werror( "sizeof returns 0" );
1337: return( bcon( i ) );
1338: }
1339:
1340: # ifndef BUG2
1341: eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1342: register ty;
1343:
1344: *a = *b = down+1;
1345: while( down > 1 ){
1346: printf( "\t" );
1347: down -= 2;
1348: }
1349: if( down ) printf( " " );
1350:
1351: ty = optype( p->in.op );
1352:
1353: printf("%o) %s, ", p, opst[p->in.op] );
1354: if( ty == LTYPE ){
1355: printf( CONFMT, p->tn.lval );
1356: printf( ", %d, ", p->tn.rval );
1357: }
1358: tprint( p->in.type );
1359: printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1360: }
1361: # endif
1362:
1363: prtdcon( p ) register NODE *p; {
1364: int i;
1365:
1366: if( p->in.op == FCON ){
1367: locctr( DATA );
1368: defalign( ALDOUBLE );
1369: deflab( i = getlab() );
1370: fincode( p->fpn.dval, SZDOUBLE );
1371: p->tn.lval = 0;
1372: p->tn.rval = -i;
1373: p->in.type = DOUBLE;
1374: p->in.op = NAME;
1375: }
1376: }
1377:
1378:
1379: int edebug = 0;
1380: ecomp( p ) register NODE *p; {
1381: # ifndef BUG2
1382: if( edebug ) fwalk( p, eprint, 0 );
1383: # endif
1384: if( !reached ){
1385: werror( "statement not reached" );
1386: reached = 1;
1387: }
1388: p = optim(p);
1389: walkf( p, prtdcon );
1390: locctr( PROG );
1391: ecode( p );
1392: tfree(p);
1393: }
1394:
1395: # ifdef STDPRTREE
1396: # ifndef ONEPASS
1397:
1398: prtree(p) register NODE *p; {
1399:
1400: register struct symtab *q;
1401: register ty;
1402:
1403: # ifdef MYPRTREE
1404: MYPRTREE(p); /* local action can be taken here; then return... */
1405: #endif
1406:
1407: ty = optype(p->in.op);
1408:
1409: printf( "%d\t", p->in.op );
1410:
1411: if( ty == LTYPE ) {
1412: printf( CONFMT, p->tn.lval );
1413: printf( "\t" );
1414: }
1415: if( ty != BITYPE ) {
1416: if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1417: else printf( "%d\t", p->tn.rval );
1418: }
1419:
1420: printf( "%o\t", p->in.type );
1421:
1422: /* handle special cases */
1423:
1424: switch( p->in.op ){
1425:
1426: case NAME:
1427: case ICON:
1428: /* print external name */
1429: if( p->tn.rval == NONAME ) printf( "\n" );
1430: else if( p->tn.rval >= 0 ){
1431: q = &stab[p->tn.rval];
1432: printf( "%s\n", exname(q->sname) );
1433: }
1434: else { /* label */
1435: printf( LABFMT, -p->tn.rval );
1436: }
1437: break;
1438:
1439: case STARG:
1440: case STASG:
1441: case STCALL:
1442: case UNARY STCALL:
1443: /* print out size */
1444: /* use lhs size, in order to avoid hassles with the structure `.' operator */
1445:
1446: /* note: p->in.left not a field... */
1447: printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1448: printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1449: break;
1450:
1451: default:
1452: printf( "\n" );
1453: }
1454:
1455: if( ty != LTYPE ) prtree( p->in.left );
1456: if( ty == BITYPE ) prtree( p->in.right );
1457:
1458: }
1459:
1460: # else
1461:
1462: p2tree(p) register NODE *p; {
1463: register ty;
1464:
1465: # ifdef MYP2TREE
1466: MYP2TREE(p); /* local action can be taken here; then return... */
1467: # endif
1468:
1469: ty = optype(p->in.op);
1470:
1471: switch( p->in.op ){
1472:
1473: case NAME:
1474: case ICON:
1475: #ifndef FLEXNAMES
1476: if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1477: #else
1478: if( p->tn.rval == NONAME ) p->in.name = "";
1479: #endif
1480: else if( p->tn.rval >= 0 ){ /* copy name from exname */
1481: register char *cp;
1482: register i;
1483: cp = exname( stab[p->tn.rval].sname );
1484: #ifndef FLEXNAMES
1485: for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
1486: #else
1487: p->in.name = tstr(cp);
1488: #endif
1489: }
1490: #ifndef FLEXNAMES
1491: else sprintf( p->in.name, LABFMT, -p->tn.rval );
1492: #else
1493: else {
1494: char temp[32];
1495: sprintf( temp, LABFMT, -p->tn.rval );
1496: p->in.name = tstr(temp);
1497: }
1498: #endif
1499: break;
1500:
1501: case STARG:
1502: case STASG:
1503: case STCALL:
1504: case UNARY STCALL:
1505: /* set up size parameters */
1506: p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1507: p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1508: break;
1509:
1510: case REG:
1511: rbusy( p->tn.rval, p->in.type );
1512: default:
1513: #ifndef FLEXNAMES
1514: p->in.name[0] = '\0';
1515: #else
1516: p->in.name = "";
1517: #endif
1518: }
1519:
1520: p->in.rall = NOPREF;
1521:
1522: if( ty != LTYPE ) p2tree( p->in.left );
1523: if( ty == BITYPE ) p2tree( p->in.right );
1524: }
1525:
1526: # endif
1527: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.