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