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