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