|
|
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 int actions;
39: register int 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 int 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 int 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 int 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: unsigned long uval;
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: if ( u ){
575: uval = val;
576: p->tn.lval *= uval;
577: }
578: else
579: p->tn.lval *= val;
580: break;
581: case DIV:
582: if( val == 0 ) uerror( "division by 0" );
583: else p->tn.lval /= val;
584: break;
585: case MOD:
586: if( val == 0 ) uerror( "division by 0" );
587: else p->tn.lval %= val;
588: break;
589: case AND:
590: p->tn.lval &= val;
591: break;
592: case OR:
593: p->tn.lval |= val;
594: break;
595: case ER:
596: p->tn.lval ^= val;
597: break;
598: case LS:
599: i = val;
600: p->tn.lval = p->tn.lval << i;
601: break;
602: case RS:
603: i = val;
604: p->tn.lval = p->tn.lval >> i;
605: break;
606:
607: case UNARY MINUS:
608: p->tn.lval = - p->tn.lval;
609: break;
610: case COMPL:
611: p->tn.lval = ~p->tn.lval;
612: break;
613: case NOT:
614: p->tn.lval = !p->tn.lval;
615: break;
616: case LT:
617: p->tn.lval = p->tn.lval < val;
618: break;
619: case LE:
620: p->tn.lval = p->tn.lval <= val;
621: break;
622: case GT:
623: p->tn.lval = p->tn.lval > val;
624: break;
625: case GE:
626: p->tn.lval = p->tn.lval >= val;
627: break;
628: case ULT:
629: p->tn.lval = (p->tn.lval-val)<0;
630: break;
631: case ULE:
632: p->tn.lval = (p->tn.lval-val)<=0;
633: break;
634: case UGE:
635: p->tn.lval = (p->tn.lval-val)>=0;
636: break;
637: case UGT:
638: p->tn.lval = (p->tn.lval-val)>0;
639: break;
640: case EQ:
641: p->tn.lval = p->tn.lval == val;
642: break;
643: case NE:
644: p->tn.lval = p->tn.lval != val;
645: break;
646: default:
647: return(0);
648: }
649: return(1);
650: }
651:
652: chkpun(p) register NODE *p; {
653:
654: /* checks p for the existance of a pun */
655:
656: /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
657:
658: /* one case is when enumerations are used: this applies only to lint */
659: /* in the other case, one operand is a pointer, the other integer type */
660: /* we check that this integer is in fact a constant zero... */
661:
662: /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
663: /* this falls out, because the LHS is never 0 */
664:
665: register NODE *q;
666: register int t1, t2;
667: register int d1, d2;
668:
669: t1 = p->in.left->in.type;
670: t2 = p->in.right->in.type;
671:
672: if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
673: if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
674: uerror( "illegal comparison of enums" );
675: return;
676: }
677: if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
678: werror( "enumeration type clash, operator %s", opst[p->in.op] );
679: return;
680: }
681:
682: if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
683: else q = p->in.left;
684:
685: if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
686: if( q->in.op != ICON || q->tn.lval != 0 ){
687: werror( "illegal combination of pointer and integer, op %s",
688: opst[p->in.op] );
689: }
690: }
691: else {
692: d1 = p->in.left->fn.cdim;
693: d2 = p->in.right->fn.cdim;
694: for( ;; ){
695: if( t1 == t2 ) {;
696: if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
697: werror( "illegal structure pointer combination" );
698: }
699: return;
700: }
701: if( ISARY(t1) || ISPTR(t1) ){
702: if( !ISARY(t2) && !ISPTR(t2) ) break;
703: if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
704: werror( "illegal array size combination" );
705: return;
706: }
707: if( ISARY(t1) ) ++d1;
708: if( ISARY(t2) ) ++d2;
709: }
710: else break;
711: t1 = DECREF(t1);
712: t2 = DECREF(t2);
713: }
714: werror( "illegal pointer combination" );
715: }
716:
717: }
718:
719: NODE *
720: stref( p ) register NODE *p; {
721:
722: TWORD t;
723: int d, s, dsc, align;
724: OFFSZ off;
725: register struct symtab *q;
726:
727: /* make p->x */
728: /* this is also used to reference automatic variables */
729:
730: q = &stab[p->in.right->tn.rval];
731: p->in.right->in.op = FREE;
732: p->in.op = FREE;
733: p = pconvert( p->in.left );
734:
735: /* make p look like ptr to x */
736:
737: if( !ISPTR(p->in.type)){
738: p->in.type = PTR+UNIONTY;
739: }
740:
741: t = INCREF( q->stype );
742: d = q->dimoff;
743: s = q->sizoff;
744:
745: p = makety( p, t, d, s );
746:
747: /* compute the offset to be added */
748:
749: off = q->offset;
750: dsc = q->sclass;
751:
752: if( dsc & FIELD ) { /* normalize offset */
753: align = ALINT;
754: s = INT;
755: off = (off/align)*align;
756: }
757: if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
758:
759: p = buildtree( UNARY MUL, p, NIL );
760:
761: /* if field, build field info */
762:
763: if( dsc & FIELD ){
764: p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
765: p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
766: }
767:
768: return( clocal(p) );
769: }
770:
771: notlval(p) register NODE *p; {
772:
773: /* return 0 if p an lvalue, 1 otherwise */
774:
775: again:
776:
777: switch( p->in.op ){
778:
779: case FLD:
780: p = p->in.left;
781: goto again;
782:
783: case UNARY MUL:
784: /* fix the &(a=b) bug, given that a and b are structures */
785: if( p->in.left->in.op == STASG ) return( 1 );
786: /* and the f().a bug, given that f returns a structure */
787: if( p->in.left->in.op == UNARY STCALL ||
788: p->in.left->in.op == STCALL ) return( 1 );
789: case NAME:
790: case OREG:
791: if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
792: case REG:
793: return(0);
794:
795: default:
796: return(1);
797:
798: }
799:
800: }
801:
802: NODE *
803: bcon( i ){ /* make a constant node with value i */
804: register NODE *p;
805:
806: p = block( ICON, NIL, NIL, INT, 0, INT );
807: p->tn.lval = i;
808: p->tn.rval = NONAME;
809: return( clocal(p) );
810: }
811:
812: NODE *
813: bpsize(p) register NODE *p; {
814: return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
815: }
816:
817: OFFSZ
818: psize( p ) NODE *p; {
819: /* p is a node of type pointer; psize returns the
820: size of the thing pointed to */
821:
822: if( !ISPTR(p->in.type) ){
823: uerror( "pointer required");
824: return( SZINT );
825: }
826: /* note: no pointers to fields */
827: return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
828: }
829:
830: NODE *
831: convert( p, f ) register NODE *p; {
832: /* convert an operand of p
833: f is either CVTL or CVTR
834: operand has type int, and is converted by the size of the other side
835: */
836:
837: register NODE *q, *r;
838:
839: q = (f==CVTL)?p->in.left:p->in.right;
840:
841: r = block( PMCONV,
842: q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
843: r = clocal(r);
844: if( f == CVTL )
845: p->in.left = r;
846: else
847: p->in.right = r;
848: return(p);
849:
850: }
851:
852: econvert( p ) register NODE *p; {
853:
854: /* change enums to ints, or appropriate types */
855:
856: register TWORD ty;
857:
858: if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
859: if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
860: else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
861: else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
862: else ty = LONG;
863: ty = ctype( ty );
864: p->fn.csiz = ty;
865: MODTYPE(p->in.type,ty);
866: if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
867: }
868: }
869:
870: NODE *
871: pconvert( p ) register NODE *p; {
872:
873: /* if p should be changed into a pointer, do so */
874:
875: if( ISARY( p->in.type) ){
876: p->in.type = DECREF( p->in.type );
877: ++p->fn.cdim;
878: return( buildtree( UNARY AND, p, NIL ) );
879: }
880: if( ISFTN( p->in.type) )
881: return( buildtree( UNARY AND, p, NIL ) );
882:
883: return( p );
884: }
885:
886: NODE *
887: oconvert(p) register NODE *p; {
888: /* convert the result itself: used for pointer and unsigned */
889:
890: switch(p->in.op) {
891:
892: case LE:
893: case LT:
894: case GE:
895: case GT:
896: if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE);
897: case EQ:
898: case NE:
899: return( p );
900:
901: case MINUS:
902: return( clocal( block( PVCONV,
903: p, bpsize(p->in.left), INT, 0, INT ) ) );
904: }
905:
906: cerror( "illegal oconvert: %d", p->in.op );
907:
908: return(p);
909: }
910:
911: NODE *
912: ptmatch(p) register NODE *p; {
913:
914: /* makes the operands of p agree; they are
915: either pointers or integers, by this time */
916: /* with MINUS, the sizes must be the same */
917: /* with COLON, the types must be the same */
918:
919: TWORD t1, t2, t;
920: int o, d2, d, s2, s;
921:
922: o = p->in.op;
923: t = t1 = p->in.left->in.type;
924: t2 = p->in.right->in.type;
925: d = p->in.left->fn.cdim;
926: d2 = p->in.right->fn.cdim;
927: s = p->in.left->fn.csiz;
928: s2 = p->in.right->fn.csiz;
929:
930: switch( o ){
931:
932: case ASSIGN:
933: case RETURN:
934: case CAST:
935: { break; }
936:
937: case MINUS:
938: { if( psize(p->in.left) != psize(p->in.right) ){
939: uerror( "illegal pointer subtraction");
940: }
941: break;
942: }
943: case COLON:
944: { if( t1 != t2 ) uerror( "illegal types in :");
945: break;
946: }
947: default: /* must work harder: relationals or comparisons */
948:
949: if( !ISPTR(t1) ){
950: t = t2;
951: d = d2;
952: s = s2;
953: break;
954: }
955: if( !ISPTR(t2) ){
956: break;
957: }
958:
959: /* both are pointers */
960: if( talign(t2,s2) < talign(t,s) ){
961: t = t2;
962: s = s2;
963: }
964: break;
965: }
966:
967: p->in.left = makety( p->in.left, t, d, s );
968: p->in.right = makety( p->in.right, t, d, s );
969: if( o!=MINUS && !logop(o) ){
970:
971: p->in.type = t;
972: p->fn.cdim = d;
973: p->fn.csiz = s;
974: }
975:
976: return(clocal(p));
977: }
978:
979: int tdebug = 0;
980:
981: NODE *
982: tymatch(p) register NODE *p; {
983:
984: /* satisfy the types of various arithmetic binary ops */
985:
986: /* rules are:
987: if assignment, op, type of LHS
988: if any float or doubles, make double
989: if any longs, make long
990: otherwise, make int
991: if either operand is unsigned, the result is...
992: */
993:
994: register TWORD t1, t2, t, tu;
995: register int o, u;
996:
997: o = p->in.op;
998:
999: t1 = p->in.left->in.type;
1000: t2 = p->in.right->in.type;
1001: if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
1002: uerror("void type illegal in expression");
1003:
1004: u = 0;
1005: if( ISUNSIGNED(t1) ){
1006: u = 1;
1007: t1 = DEUNSIGN(t1);
1008: }
1009: if( ISUNSIGNED(t2) ){
1010: u = 1;
1011: t2 = DEUNSIGN(t2);
1012: }
1013:
1014: if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
1015: if( t2 == CHAR || t2 == SHORT ) t2 = INT;
1016:
1017: if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE;
1018: else if( t1==LONG || t2==LONG ) t = LONG;
1019: else t = INT;
1020:
1021: if( asgop(o) ){
1022: tu = p->in.left->in.type;
1023: t = t1;
1024: }
1025: else {
1026: tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1027: }
1028:
1029: /* because expressions have values that are at least as wide
1030: as INT or UNSIGNED, the only conversions needed
1031: are those involving FLOAT/DOUBLE, and those
1032: from LONG to INT and ULONG to UNSIGNED */
1033:
1034: if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu );
1035:
1036: if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu );
1037:
1038: if( asgop(o) ){
1039: p->in.type = p->in.left->in.type;
1040: p->fn.cdim = p->in.left->fn.cdim;
1041: p->fn.csiz = p->in.left->fn.csiz;
1042: }
1043: else if( !logop(o) ){
1044: p->in.type = tu;
1045: p->fn.cdim = 0;
1046: p->fn.csiz = t;
1047: }
1048:
1049: # ifndef BUG1
1050: if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
1051: # endif
1052:
1053: return(p);
1054: }
1055:
1056: NODE *
1057: makety( p, t, d, s ) register NODE *p; TWORD t; {
1058: /* make p into type t by inserting a conversion */
1059:
1060: if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
1061: if( t == p->in.type ){
1062: p->fn.cdim = d;
1063: p->fn.csiz = s;
1064: return( p );
1065: }
1066:
1067: if( t & TMASK ){
1068: /* non-simple type */
1069: return( block( PCONV, p, NIL, t, d, s ) );
1070: }
1071:
1072: if( p->in.op == ICON ){
1073: if( t==DOUBLE||t==FLOAT ){
1074: p->in.op = FCON;
1075: if( ISUNSIGNED(p->in.type) ){
1076: p->fpn.dval = (unsigned CONSZ) p->tn.lval;
1077: }
1078: else {
1079: p->fpn.dval = p->tn.lval;
1080: }
1081:
1082: p->in.type = p->fn.csiz = t;
1083: return( clocal(p) );
1084: }
1085: }
1086:
1087: return( block( SCONV, p, NIL, t, d, s ) );
1088:
1089: }
1090:
1091: NODE *
1092: block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
1093:
1094: register NODE *p;
1095:
1096: p = talloc();
1097: p->in.op = o;
1098: p->in.left = l;
1099: p->in.right = r;
1100: p->in.type = t;
1101: p->fn.cdim = d;
1102: p->fn.csiz = s;
1103: return(p);
1104: }
1105:
1106: icons(p) register NODE *p; {
1107: /* if p is an integer constant, return its value */
1108: int val;
1109:
1110: if( p->in.op != ICON ){
1111: uerror( "constant expected");
1112: val = 1;
1113: }
1114: else {
1115: val = p->tn.lval;
1116: if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
1117: }
1118: tfree( p );
1119: return(val);
1120: }
1121:
1122: /* the intent of this table is to examine the
1123: operators, and to check them for
1124: correctness.
1125:
1126: The table is searched for the op and the
1127: modified type (where this is one of the
1128: types INT (includes char and short), LONG,
1129: DOUBLE (includes FLOAT), and POINTER
1130:
1131: The default action is to make the node type integer
1132:
1133: The actions taken include:
1134: PUN check for puns
1135: CVTL convert the left operand
1136: CVTR convert the right operand
1137: TYPL the type is determined by the left operand
1138: TYPR the type is determined by the right operand
1139: TYMATCH force type of left and right to match, by inserting conversions
1140: PTMATCH like TYMATCH, but for pointers
1141: LVAL left operand must be lval
1142: CVTO convert the op
1143: NCVT do not convert the operands
1144: OTHER handled by code
1145: NCVTR convert the left operand, not the right...
1146:
1147: */
1148:
1149: # define MINT 01 /* integer */
1150: # define MDBI 02 /* integer or double */
1151: # define MSTR 04 /* structure */
1152: # define MPTR 010 /* pointer */
1153: # define MPTI 020 /* pointer or integer */
1154: # define MENU 040 /* enumeration variable or member */
1155:
1156: opact( p ) NODE *p; {
1157:
1158: register int mt12, mt1, mt2, o;
1159:
1160: mt12 = 0;
1161:
1162: switch( optype(o=p->in.op) ){
1163:
1164: case BITYPE:
1165: mt12=mt2 = moditype( p->in.right->in.type );
1166: case UTYPE:
1167: mt12 &= (mt1 = moditype( p->in.left->in.type ));
1168:
1169: }
1170:
1171: switch( o ){
1172:
1173: case NAME :
1174: case STRING :
1175: case ICON :
1176: case FCON :
1177: case CALL :
1178: case UNARY CALL:
1179: case UNARY MUL:
1180: { return( OTHER ); }
1181: case UNARY MINUS:
1182: if( mt1 & MDBI ) return( TYPL );
1183: break;
1184:
1185: case COMPL:
1186: if( mt1 & MINT ) return( TYPL );
1187: break;
1188:
1189: case UNARY AND:
1190: { return( NCVT+OTHER ); }
1191: case INIT:
1192: case CM:
1193: case NOT:
1194: case CBRANCH:
1195: case ANDAND:
1196: case OROR:
1197: return( 0 );
1198:
1199: case MUL:
1200: case DIV:
1201: if( mt12 & MDBI ) return( TYMATCH );
1202: break;
1203:
1204: case MOD:
1205: case AND:
1206: case OR:
1207: case ER:
1208: if( mt12 & MINT ) return( TYMATCH );
1209: break;
1210:
1211: case LS:
1212: case RS:
1213: if( mt12 & MINT ) return( TYMATCH+OTHER );
1214: break;
1215:
1216: case EQ:
1217: case NE:
1218: case LT:
1219: case LE:
1220: case GT:
1221: case GE:
1222: if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
1223: if( mt12 & MDBI ) return( TYMATCH+CVTO );
1224: else if( mt12 & MPTR ) return( PTMATCH+PUN );
1225: else if( mt12 & MPTI ) return( PTMATCH+PUN );
1226: else break;
1227:
1228: case QUEST:
1229: case COMOP:
1230: if( mt2&MENU ) return( TYPR+NCVTR );
1231: return( TYPR );
1232:
1233: case STREF:
1234: return( NCVTR+OTHER );
1235:
1236: case FORCE:
1237: return( TYPL );
1238:
1239: case COLON:
1240: if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
1241: else if( mt12 & MDBI ) return( TYMATCH );
1242: else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1243: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1244: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1245: else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1246: break;
1247:
1248: case ASSIGN:
1249: case RETURN:
1250: if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1251: case CAST:
1252: if(o==CAST && mt1==0)return(TYPL+TYMATCH);
1253: if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
1254: else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
1255: else if( mt12 == 0 ) break;
1256: else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
1257: else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1258: break;
1259:
1260: case ASG LS:
1261: case ASG RS:
1262: if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1263: break;
1264:
1265: case ASG MUL:
1266: case ASG DIV:
1267: if( mt12 & MDBI ) return( LVAL+TYMATCH );
1268: break;
1269:
1270: case ASG MOD:
1271: case ASG AND:
1272: case ASG OR:
1273: case ASG ER:
1274: if( mt12 & MINT ) return( LVAL+TYMATCH );
1275: break;
1276:
1277: case ASG PLUS:
1278: case ASG MINUS:
1279: case INCR:
1280: case DECR:
1281: if( mt12 & MDBI ) return( TYMATCH+LVAL );
1282: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1283: break;
1284:
1285: case MINUS:
1286: if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1287: if( mt2 & MPTR ) break;
1288: case PLUS:
1289: if( mt12 & MDBI ) return( TYMATCH );
1290: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1291: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1292:
1293: }
1294: uerror( "operands of %s have incompatible types", opst[o] );
1295: return( NCVT );
1296: }
1297:
1298: moditype( ty ) TWORD ty; {
1299:
1300: switch( ty ){
1301:
1302: case TVOID:
1303: case UNDEF:
1304: return(0); /* type is void */
1305: case ENUMTY:
1306: case MOETY:
1307: return( MENU );
1308:
1309: case STRTY:
1310: case UNIONTY:
1311: return( MSTR );
1312:
1313: case CHAR:
1314: case SHORT:
1315: case UCHAR:
1316: case USHORT:
1317: return( MINT|MPTI|MDBI );
1318: case UNSIGNED:
1319: case ULONG:
1320: case INT:
1321: case LONG:
1322: return( MINT|MDBI|MPTI );
1323: case FLOAT:
1324: case DOUBLE:
1325: return( MDBI );
1326: default:
1327: return( MPTR|MPTI );
1328:
1329: }
1330: }
1331:
1332: NODE *
1333: doszof( p ) register NODE *p; {
1334: /* do sizeof p */
1335: int i;
1336:
1337: /* whatever is the meaning of this if it is a bitfield? */
1338: i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1339:
1340: tfree(p);
1341: if( i <= 0 ) werror( "sizeof returns 0" );
1342: return( bcon( i ) );
1343: }
1344:
1345: # ifndef BUG2
1346: eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1347: register int ty;
1348:
1349: *a = *b = down+1;
1350: while( down > 1 ){
1351: printf( "\t" );
1352: down -= 2;
1353: }
1354: if( down ) printf( " " );
1355:
1356: ty = optype( p->in.op );
1357:
1358: printf("%o) %s, ", p, opst[p->in.op] );
1359: if( ty == LTYPE ){
1360: printf( CONFMT, p->tn.lval );
1361: printf( ", %d, ", p->tn.rval );
1362: }
1363: tprint( p->in.type );
1364: printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1365: }
1366: # endif
1367:
1368: # ifndef PRTDCON
1369: prtdcon( p ) register NODE *p; {
1370: int i;
1371:
1372: if( p->in.op == FCON ){
1373: locctr( DATA );
1374: defalign( ALDOUBLE );
1375: deflab( i = getlab() );
1376: # ifndef SFCON
1377: fincode( p->fpn.dval, SZDOUBLE );
1378: p->in.type = DOUBLE;
1379: # else
1380: p->in.type = fincode( p->fpn.dval, 0 );
1381: # endif
1382: p->tn.lval = 0;
1383: p->tn.rval = -i;
1384: p->in.op = NAME;
1385: }
1386: }
1387: # endif
1388:
1389:
1390: int edebug = 0;
1391: ecomp( p ) register NODE *p; {
1392: extern prtdcon();
1393:
1394: # ifndef BUG2
1395: if( edebug ) fwalk( p, eprint, 0 );
1396: # endif
1397: if( !reached ){
1398: werror( "statement not reached" );
1399: reached = 1;
1400: }
1401: p = optim(p);
1402: walkf( p, prtdcon );
1403: locctr( PROG );
1404: ecode( p );
1405: tfree(p);
1406: }
1407:
1408: # ifdef STDPRTREE
1409: # ifndef ONEPASS
1410:
1411: prtree(p) register NODE *p; {
1412:
1413: register struct symtab *q;
1414: register int ty;
1415:
1416: # ifdef MYPRTREE
1417: MYPRTREE(p); /* local action can be taken here; then return... */
1418: #endif
1419:
1420: ty = optype(p->in.op);
1421:
1422: printf( "%d\t", p->in.op );
1423:
1424: if( ty == LTYPE ) {
1425: printf( CONFMT, p->tn.lval );
1426: printf( "\t" );
1427: }
1428: if( ty != BITYPE ) {
1429: if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1430: else printf( "%d\t", p->tn.rval );
1431: }
1432:
1433: printf( "%o\t", p->in.type );
1434:
1435: /* handle special cases */
1436:
1437: switch( p->in.op ){
1438:
1439: case NAME:
1440: case ICON:
1441: /* print external name */
1442: if( p->tn.rval == NONAME ) printf( "\n" );
1443: else if( p->tn.rval >= 0 ){
1444: q = &stab[p->tn.rval];
1445: printf( "%s\n", exname(q->sname) );
1446: }
1447: else { /* label */
1448: printf( LABFMT, -p->tn.rval );
1449: }
1450: break;
1451:
1452: case STARG:
1453: case STASG:
1454: case STCALL:
1455: case UNARY STCALL:
1456: /* print out size */
1457: /* use lhs size, in order to avoid hassles with the structure `.' operator */
1458:
1459: /* note: p->in.left not a field... */
1460: printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1461: printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1462: break;
1463:
1464: default:
1465: printf( "\n" );
1466: }
1467:
1468: if( ty != LTYPE ) prtree( p->in.left );
1469: if( ty == BITYPE ) prtree( p->in.right );
1470:
1471: }
1472:
1473: # else
1474:
1475: p2tree(p) register NODE *p; {
1476: register int ty;
1477:
1478: # ifdef MYP2TREE
1479: MYP2TREE(p); /* local action can be taken here; then return... */
1480: # endif
1481:
1482: ty = optype(p->in.op);
1483:
1484: switch( p->in.op ){
1485:
1486: case NAME:
1487: case ICON:
1488: #ifndef FLEXNAMES
1489: if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1490: #else
1491: if( p->tn.rval == NONAME ) p->in.name = "";
1492: #endif
1493: else if( p->tn.rval >= 0 ){ /* copy name from exname */
1494: register char *cp;
1495: register int i;
1496: cp = exname( stab[p->tn.rval].sname );
1497: #ifndef FLEXNAMES
1498: for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
1499: #else
1500: p->in.name = tstr(cp);
1501: #endif
1502: }
1503: #ifndef FLEXNAMES
1504: else sprintf( p->in.name, LABFMT, -p->tn.rval );
1505: #else
1506: else {
1507: char temp[32];
1508: sprintf( temp, LABFMT, -p->tn.rval );
1509: p->in.name = tstr(temp);
1510: }
1511: #endif
1512: break;
1513:
1514: case STARG:
1515: case STASG:
1516: case STCALL:
1517: case UNARY STCALL:
1518: /* set up size parameters */
1519: p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1520: p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1521: break;
1522:
1523: case REG:
1524: rbusy( p->tn.rval, p->in.type );
1525: default:
1526: #ifndef FLEXNAMES
1527: p->in.name[0] = '\0';
1528: #else
1529: p->in.name = "";
1530: #endif
1531: }
1532:
1533: p->in.rall = NOPREF;
1534:
1535: if( ty != LTYPE ) p2tree( p->in.left );
1536: if( ty == BITYPE ) p2tree( p->in.right );
1537: }
1538:
1539: # endif
1540: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.