|
|
1.1 root 1: /* @(#) trees.c: 1.4 5/3/84 */
2:
3: # include "mfile1.h"
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 address units
24: ** (NAME really means "STATIC VARIABLE")
25: ** ICON: lval has the value
26: ** rval has the STAB index, or - label number,
27: ** if a name whose address is in the constant
28: ** rval = NONAME means no name
29: ** VAUTO: automatic name: lval has offset in address units
30: ** VPARAM: parameter: lval has offset in address units
31: ** REG: rval is reg. number
32: **
33: */
34: extern int maxarg;
35:
36: TWORD
37: indtype( t )
38: register TWORD t;
39: {
40: /* return the type of an intermediate expression of type t */
41: switch( t )
42: {
43:
44: case CHAR:
45: case SHORT:
46: return( INT );
47:
48: case UCHAR:
49: case USHORT:
50: return( UNSIGNED );
51:
52: case FLOAT:
53: return( DOUBLE );
54:
55: }
56: return( t );
57: }
58:
59: int bdebug = 0;
60: extern ddebug;
61:
62: # ifndef XI
63: NODE *
64: xicolon( l, r1, r2 ) register NODE *l, *r1, *r2;
65:
66: {
67: uerror( "syntax error: colon in subscript" );
68: tfree( r2 );
69: return( buildtree( LB, l, r1 ) );
70: }
71: # endif
72:
73: NODE *
74: buildtree( o, l, r )
75: register NODE *l, *r;
76: register o;
77: {
78: register NODE *p, *q;
79: register actions;
80: register opty;
81: register struct symtab *sp;
82: register NODE *lr, *ll;
83: int i;
84:
85: # ifndef NODBG
86: if( bdebug )
87: printf( "buildtree( %s, %d, %d )\n", opst[o], l-node, r-node );
88: # endif
89:
90: /* special case to recognize subscripting explicitly */
91:
92: # ifdef XI
93: if( o == LB && l->tn.type == LONG )
94: return( xicolon( l, r, (NODE *) 0 ) );
95: # endif
96:
97: if( o == LB ) return( buildtree( STAR, buildtree( PLUS, l, r ), NIL ) );
98: opty = optype(o);
99:
100: /* check for constants */
101:
102: if( o == NOT && l->in.op == ICON && hflag )
103: {
104: werror( "constant argument to NOT" );
105: }
106:
107: else if( o==UNARY MINUS && l->in.op==FCON )
108: {
109: l->fpn.dval = -l->fpn.dval;
110: return(l);
111: }
112:
113: else if( o==QUEST && l->in.op==ICON && l->tn.rval==NONAME )
114: {
115: l->in.op = FREE;
116: r->in.op = FREE;
117: if( l->tn.lval )
118: {
119: tfree( r->in.right );
120: return( r->in.left );
121: }
122: else
123: {
124: tfree( r->in.left );
125: return( r->in.right );
126: }
127: }
128:
129: else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) )
130: goto ccwarn;
131:
132: else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON )
133: {
134:
135: switch( o )
136: {
137:
138: case ULT:
139: case UGT:
140: case ULE:
141: case UGE:
142: case LT:
143: case GT:
144: case LE:
145: case GE:
146: case EQ:
147: case NE:
148: case ANDAND:
149: case OROR:
150: case CBRANCH:
151:
152: ccwarn:
153: if( hflag ) werror( "constant in conditional context" );
154: }
155: }
156:
157: /* we make a real node, and look for shrinking later */
158:
159: p = block( o, l, r, INT, 0, INT );
160:
161: actions = opact(p);
162: # ifdef MYOPACT
163: actions = MYOPACT(p,actions);
164: # endif
165:
166: if( actions&LVAL )
167: {
168: /* check left descendent */
169: if( notlval(p->in.left) )
170: {
171: uerror( "illegal lhs of assignment operator" );
172: }
173: }
174:
175: if( actions & NCVTR )
176: {
177: p->in.left = pconvert( p->in.left );
178: }
179: else if( !(actions & NCVT ) )
180: {
181: switch( opty )
182: {
183:
184: case BITYPE:
185: p->in.right = pconvert( p->in.right );
186: case UTYPE:
187: if( !(actions&LVAL) )
188: p->in.left = pconvert( p->in.left );
189:
190: }
191: }
192:
193: if( (actions&PUN) && (o!=CAST||cflag) )
194: {
195: chkpun(p);
196: }
197:
198: if( actions & (TYPL|TYPR) )
199: {
200:
201: q = (actions&TYPL) ? p->in.left : p->in.right;
202:
203: p->in.type = q->in.type;
204: p->fn.cdim = q->fn.cdim;
205: p->fn.csiz = q->fn.csiz;
206: }
207:
208: if( actions & CVTL ) p = convert( p, CVTL );
209: if( actions & CVTR ) p = convert( p, CVTR );
210:
211: if( actions & TYMATCH ) p = tymatch(p);
212: if( actions & PTMATCH ) p = ptmatch(p);
213:
214: if( actions & SPFLG ) p = clocal(p);
215:
216: if( actions & OTHER )
217: {
218: l = p->in.left;
219: r = p->in.right;
220:
221: switch(o)
222: {
223:
224: case NAME:
225: sp = &stab[idname];
226: if( sp->stype == UNDEF )
227: {
228: uerror( "%s undefined", sp->sname );
229: /* make p look reasonable */
230: p->in.type = p->fn.cdim = p->fn.csiz = INT;
231: p->tn.rval = idname;
232: p->tn.lval = 0;
233: defid( p, SNULL );
234: break;
235: }
236: #if defined(M32B) && defined(IMPREGAL)
237: p->in.pad[0] = '@'; /*mark as un-raname()'d*/
238: #endif
239: p->in.type = sp->stype;
240: p->fn.cdim = sp->dimoff;
241: p->fn.csiz = sp->sizoff;
242: /* special case: MOETY is really an ICON... */
243: if( p->in.type == MOETY )
244: {
245: p->tn.rval = NONAME;
246: p->tn.lval = sp->offset;
247: p->fn.cdim = 0;
248: p->in.type = ENUMTY;
249: p->in.op = ICON;
250: }
251: else
252: {
253: switch( sp->sclass )
254: {
255:
256: case AUTO:
257: p->in.op = VAUTO;
258: p->tn.rval = NONAME;
259: p->tn.lval = BITOOR(sp->offset);
260: break;
261:
262: case PARAM:
263: p->in.op = VPARAM;
264: p->tn.rval = NONAME;
265: p->tn.lval = BITOOR(sp->offset);
266: break;
267:
268: case REGISTER:
269: p->in.op = REG;
270: p->tn.lval = 0;
271: p->tn.rval = sp->offset;
272: break;
273:
274: case ULABEL:
275: case LABEL:
276: case STATIC:
277: if( sp->slevel != 0 )
278: {
279: p->tn.lval = 0;
280: p->tn.rval = -sp->offset;
281: break;
282: }
283: /* FALLTHRU */
284:
285: default:
286: p->tn.lval = 0;
287: p->tn.rval = idname;
288: }
289: }
290: break;
291:
292: case ICON:
293: p->in.type = INT;
294: p->fn.cdim = 0;
295: p->fn.csiz = INT;
296: break;
297:
298: case STRING:
299: p->in.op = NAME;
300: p->in.type = CHAR+ARY;
301: p->tn.lval = 0;
302: p->tn.rval = NOLAB;
303: p->fn.cdim = curdim;
304: p->fn.csiz = CHAR;
305: break;
306:
307: case FCON:
308: p->tn.lval = 0;
309: p->tn.rval = 0;
310: p->in.type = DOUBLE;
311: p->fn.cdim = 0;
312: p->fn.csiz = DOUBLE;
313: break;
314:
315: case STREF:
316: /* p->x turned into *(p+offset) */
317: /* rhs must be a name; check correctness */
318:
319: i = r->tn.rval;
320: if(i<0 || i>=SYMTSZ || ((sp= &stab[i])->sclass != MOS &&
321: sp->sclass != MOU && !(sp->sclass&FIELD)) )
322: {
323: uerror( "structure/union member required" );
324: break;
325: }
326: else
327: /* if this name is non-unique, find right one */
328: if( stab[i].sflags&SNONUNIQ && (l->in.type==PTR+STRTY ||
329: l->in.type == PTR+UNIONTY) &&
330: (l->fn.csiz+1) >= 0 )
331: {
332: /* nonunique name && structure defined */
333: char * memnam, * tabnam;
334: register j;
335: int memi;
336: j=dimtab[l->fn.csiz+1];
337: for( ; (memi=dimtab[j]) >= 0; ++j )
338: {
339: tabnam = stab[memi].sname;
340: memnam = stab[i].sname;
341: # ifndef NODBG
342: if( ddebug>1 )
343: {
344: printf("member %s==%s?\n",
345: memnam, tabnam);
346: }
347: # endif
348: if( stab[memi].sflags & SNONUNIQ )
349: {
350: if ( memnam != tabnam )
351: continue;
352: r->tn.rval = i = memi;
353: break;
354: }
355: continue;
356: }
357: if( memi < 0 )
358: uerror("illegal member use: %s",
359: stab[i].sname);
360: }
361: else
362: {
363: register j;
364: if( l->in.type != PTR+STRTY &&
365: l->in.type != PTR+UNIONTY )
366: {
367: if( stab[i].sflags & SNONUNIQ )
368: {
369: uerror(
370: "nonunique name demands struct/union or struct/union pointer" );
371: }
372: else werror(
373: "struct/union or struct/union pointer required" );
374: }
375: else if( (j=l->fn.csiz+1)<0 )
376: cerror( "undefined structure or union");
377: else if( !chkstr( i, dimtab[j],
378: DECREF(l->in.type) ) )
379: {
380: werror( "illegal member use: %s",
381: stab[i].sname );
382: }
383: }
384: p = stref( p );
385: break;
386:
387: case STAR:
388: if( l->in.op == UNARY AND )
389: {
390: p->in.op = l->in.op = FREE;
391: p = l->in.left;
392: }
393: if( !ISPTR(l->in.type) ) uerror("illegal indirection");
394: p->in.type = DECREF(l->in.type);
395: p->fn.cdim = l->fn.cdim;
396: p->fn.csiz = l->fn.csiz;
397: break;
398:
399: case UNARY AND:
400: switch( l->in.op )
401: {
402:
403: case STAR:
404: p->in.op = l->in.op = FREE;
405: p = l->in.left;
406: case NAME:
407: case VAUTO:
408: case VPARAM:
409: case TEMP:
410: case STCALL:
411: case UNARY STCALL:
412: refinc:
413: p->in.type = INCREF( l->in.type );
414: p->fn.cdim = l->fn.cdim;
415: p->fn.csiz = l->fn.csiz;
416: break;
417:
418: case RNODE:
419: #ifdef TMPSRET
420: /* don't bother, let optim clean up */
421: if (simpstr(l->fn.cdim, l->fn.csiz) != STRTY)
422: goto refinc;
423:
424: p->in.op = STAR;
425: p->in.type = STRTY;
426: p->fn.csiz = l->fn.csiz;
427: p->fn.cdim = l->fn.cdim;
428: l->in.op = FREE;
429: idname = lookup(hash(".stfake"), 0);
430: p->in.left = buildtree(NAME, NIL, NIL);
431: p->in.left->fn.csiz = p->fn.csiz;
432: p->in.left->fn.cdim = p->fn.cdim;
433: break;
434: #else
435: goto refinc;
436: #endif
437: case COMOP:
438: lr = buildtree( UNARY AND, l->in.right, NIL );
439: p->in.op = l->in.op = FREE;
440: p = buildtree( COMOP, l->in.left, lr );
441: break;
442:
443: case QUEST:
444: lr = buildtree( UNARY AND,
445: l->in.right->in.right, NIL );
446: ll = buildtree( UNARY AND,
447: l->in.right->in.left, NIL );
448: p->in.op = l->in.op = l->in.right->in.op = FREE;
449: p = buildtree( QUEST, l->in.left,
450: buildtree( COLON, ll, lr ) );
451: break;
452:
453: default:
454: uerror( "unacceptable operand of &" );
455: break;
456: }
457: break;
458:
459: case RETURN:
460: case ASSIGN:
461: case CAST:
462: /* structure assignment */
463: /* take the addresses of the two sides; then make an
464: ** operator using STASG and
465: ** the addresses of left and right
466: */
467:
468: {
469: register TWORD t;
470: register d, s, sz;
471:
472: if( l->fn.csiz != r->fn.csiz )
473: uerror(
474: "assignment of different structures" );
475:
476: r = buildtree( UNARY AND, r, NIL );
477: l = buildtree( UNARY AND, l, NIL );
478: t = r->in.type;
479: d = r->fn.cdim;
480: s = r->fn.csiz;
481: #ifdef ENDSTRUCT
482: sz = tsize( STRTY, d, s );
483: l = aadjust( l, sz );
484: r = aadjust( r, sz );
485: #endif
486:
487: l = block( STASG, l, r, t, d, s );
488:
489: if( o == RETURN )
490: {
491: p->in.op = FREE;
492: p = l;
493: break;
494: }
495:
496: p->in.op = STAR;
497: p->in.left = clocal(l);
498: p->in.right = NIL;
499: break;
500: }
501: case COLON:
502: /* structure colon */
503:
504: if( l->fn.csiz != r->fn.csiz )
505: uerror( "type clash in conditional" );
506: break;
507:
508: case CALL:
509: i = 0;
510: p->in.right = r = strargs( p->in.right, &i );
511: if( i > maxarg ) maxarg = i;
512: case UNARY CALL:
513: if( !ISPTR(l->in.type)) uerror("illegal function");
514: p->in.type = DECREF(l->in.type);
515: if( !ISFTN(p->in.type)) uerror("illegal function");
516: p->in.type = DECREF( p->in.type );
517: p->fn.cdim = l->fn.cdim;
518: p->fn.csiz = l->fn.csiz;
519: if( l->in.op == UNARY AND &&
520: l->in.left->in.op == NAME &&
521: l->in.left->tn.rval >= 0 &&
522: l->in.left->tn.rval != NONAME &&
523: ((i=stab[l->in.left->tn.rval].sclass)==FORTRAN
524: || i == UFORTRAN ) )
525: {
526: p->in.op += (FORTCALL-CALL);
527: }
528: if( p->in.type == STRTY || p->in.type == UNIONTY )
529: {
530: /* function returning structure */
531: /* function really returns ptr with * */
532:
533: # ifdef ARGSRET
534: /* set aside argument space for return val */
535: i = tsize( p->in.type, p->fn.cdim, p->fn.csiz );
536: /* alignment??? */
537: if( i > maxarg ) maxarg = i;
538: # endif
539: p->in.op += STCALL-CALL;
540: p->in.type = INCREF( p->in.type );
541: p = buildtree( STAR, p, NIL );
542: break;
543: }
544:
545: /* fix up type of return value from call */
546: {
547: register TWORD t;
548: t = indtype( p->tn.type );
549: if( t != p->tn.type )
550: {
551: p->fn.csiz = p->tn.type = t;
552: }
553: }
554: # ifdef ARGALLRET
555: /* set aside argument space for return val */
556: i = tsize( p->in.type, p->fn.cdim, p->fn.csiz );
557: /* alignment??? */
558: if( i > maxarg ) maxarg = i;
559: # endif
560: break;
561:
562: case ANDAND :
563: case OROR :
564: /* change array or function operand to pointer constant */
565: if ( ISARY( r->in.type) )
566: {
567: r->in.type = DECREF( r->in.type );
568: ++r->fn.cdim;
569: p->in.right = buildtree( UNARY AND, r, NIL );
570: }
571: else if ( ISFTN( r->in.type) )
572: p->in.right = buildtree( UNARY AND, r, NIL );
573: case CBRANCH :
574: case NOT :
575: /* change array or function operand to pointer constant */
576: if ( ISARY( l->in.type) )
577: {
578: l->in.type = DECREF( l->in.type );
579: ++l->fn.cdim;
580: p->in.left = buildtree( UNARY AND, l, NIL );
581: }
582: else if ( ISFTN( l->in.type) )
583: p->in.left = buildtree( UNARY AND, l, NIL );
584:
585: break;
586:
587: default:
588: cerror( "other code %d", o );
589: }
590:
591: }
592:
593: if( actions & CVTO ) p = oconvert(p);
594: p = clocal(conval(p));
595:
596: # ifndef NODBG
597: if( bdebug ) eprint(p);
598: # endif
599: return(p);
600:
601: }
602:
603: NODE *
604: strargs( p, off )
605: register NODE *p;
606: register *off;
607: {
608: /* rewrite arguments */
609: /* allocate the arguments at *off, and update *off */
610: register TWORD t;
611: int workoff;
612:
613: t = p->fn.type;
614: if( p->in.op == CM )
615: {
616: #if defined(BACKARGS) && defined(BACKPARAM) || \
617: !defined(BACKARGS) && !defined(BACKPARAM)
618:
619: p->in.left = strargs( p->in.left, off );
620: p->in.right = strargs( p->in.right, off );
621:
622: #else
623:
624: p->in.right = strargs(p->in.right, off);
625: p->in.left = strargs(p->in.left, off);
626:
627: #endif
628: return( p );
629: }
630:
631: p = block( STARG, p, NIL, t, p->fn.cdim, p->fn.csiz );
632: if( t == STRTY || t == UNIONTY )
633: {
634: p->in.left = buildtree( UNARY AND, p->in.left, NIL );
635: }
636: else
637: {
638: p->in.op = FUNARG;
639: }
640:
641: SETOFF( *off, talign( t, p->fn.csiz ) );
642: workoff = tsize( t, p->fn.cdim, p->fn.csiz );
643:
644: #ifdef BACKARGS
645: *off += workoff;
646: p->tn.rval = -*off;
647: #else
648: p->tn.rval = *off;
649: *off += workoff;
650: #endif
651: return( clocal(p) );
652: }
653:
654: chkstr( i, j, type )
655: register TWORD type;
656: register i,j;
657: {
658: /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
659: /* i has been checked to contain a MOS or MOU */
660: /* j is the index in dimtab of the members... */
661: register k, kk;
662:
663: extern int ddebug;
664:
665: # ifndef NODBG
666: if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
667: # endif
668: if( (k = j) < 0 ) uerror( "undefined structure or union" );
669: else
670: {
671: for( ; (kk = dimtab[k] ) >= 0; ++k )
672: {
673: if( kk >= SYMTSZ )
674: {
675: cerror( "gummy structure" );
676: return(1);
677: }
678: if( kk == i ) return( 1 );
679: switch( stab[kk].stype )
680: {
681:
682: case STRTY:
683: case UNIONTY:
684: if( type == STRTY ) continue; /* no recursive looking for strs */
685: if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) )
686: {
687: if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */
688: werror(
689: "illegal member use: perhaps %s.%s?",
690: stab[kk].sname, stab[i].sname);
691: return(1);
692: }
693: }
694: }
695: }
696: return( 0 );
697: }
698:
699: NODE *
700: conval( p )
701: register NODE *p;
702: {
703: register NODE *l, *r;
704: register o, i, f, u;
705: register CONSZ val;
706:
707: f = (p->tn.type==FLOAT || p->tn.type == DOUBLE);
708: u = ISUNSIGNED(p->tn.type);
709:
710: switch( optype(o = p->tn.op) )
711: {
712: case BITYPE:
713: l = p->in.left;
714: r = p->in.right;
715: break;
716:
717: case UTYPE:
718: r = l = p->in.left;
719: break;
720:
721: case LTYPE:
722: return( p );
723: }
724:
725: if( l->tn.op != ( f ? FCON : ICON ) ) return( p );
726: if( r->tn.op != ( f ? FCON : ICON ) ) return( p );
727:
728: if( !f )
729: {
730: /* weed out unprofitable cases */
731: val = r->tn.lval;
732: if( l->tn.rval != NONAME && r->tn.rval != NONAME ) return(p);
733: if( r->tn.rval != NONAME && o!=PLUS ) return(p);
734: if( l->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(p);
735: }
736: else if( logop(o) ) return( p );
737:
738: switch( o )
739: {
740:
741: case PLUS:
742: if( f )
743: {
744: l->fpn.dval += r->fpn.dval;
745: break;
746: }
747: l->tn.lval += val;
748: if( l->tn.rval == NONAME )
749: {
750: l->tn.rval = r->tn.rval;
751: l->in.type = r->in.type;
752: }
753: break;
754:
755: case MINUS:
756: if( f ) l->fpn.dval -= r->fpn.dval;
757: else l->tn.lval -= val;
758: break;
759:
760: case MUL:
761: if( f ) l->fpn.dval *= r->fpn.dval;
762: else l->tn.lval *= val;
763: break;
764:
765: case DIV:
766: if( f )
767: {
768: if( r->fpn.dval == 0. ) uerror( "division by 0" );
769: else l->fpn.dval /= r->fpn.dval;
770: }
771: else
772: {
773: if( val == 0 ) uerror( "division by 0" );
774: else if( u )
775: l->tn.lval = (unsigned long)l->tn.lval / val;
776: else l->tn.lval /= val;
777: }
778: break;
779:
780: case MOD:
781: if( val == 0 ) uerror( "division by 0" );
782: else if( u ) l->tn.lval = (unsigned long)l->tn.lval % val;
783: else l->tn.lval %= val;
784: break;
785:
786: case AND:
787: l->tn.lval &= val;
788: break;
789:
790: case OR:
791: l->tn.lval |= val;
792: break;
793:
794: case ER:
795: l->tn.lval ^= val;
796: break;
797:
798: case LS:
799: i = val;
800: l->tn.lval = l->tn.lval << i;
801: break;
802:
803: case RS:
804: i = val;
805: if( u ) l->tn.lval = (unsigned long)l->tn.lval >> i;
806: else l->tn.lval = l->tn.lval >> i;
807: break;
808:
809: case UNARY MINUS:
810: if( f ) l->fpn.dval = -l->fpn.dval;
811: else l->tn.lval = - l->tn.lval;
812: break;
813:
814: case COMPL:
815: l->tn.lval = ~l->tn.lval;
816: break;
817:
818: case NOT:
819: if( l->tn.type == FLOAT || l->tn.type == DOUBLE )
820: {
821: l->tn.op = ICON;
822: l->tn.lval = !l->fpn.dval;
823: }
824: else l->tn.lval = !l->tn.lval;
825: break;
826:
827: case LT:
828: l->tn.lval = l->tn.lval < val;
829: break;
830:
831: case LE:
832: l->tn.lval = l->tn.lval <= val;
833: break;
834:
835: case GT:
836: l->tn.lval = l->tn.lval > val;
837: break;
838:
839: case GE:
840: l->tn.lval = l->tn.lval >= val;
841: break;
842:
843: case ULT:
844: l->tn.lval = (l->tn.lval-val)<0;
845: break;
846:
847: case ULE:
848: l->tn.lval = (l->tn.lval-val)<=0;
849: break;
850:
851: case UGE:
852: l->tn.lval = (l->tn.lval-val)>=0;
853: break;
854:
855: case UGT:
856: l->tn.lval = (l->tn.lval-val)>0;
857: break;
858:
859: case EQ:
860: l->tn.lval = l->tn.lval == val;
861: break;
862:
863: case NE:
864: l->tn.lval = l->tn.lval != val;
865: break;
866:
867: default:
868: return(p);
869: }
870:
871: if( l != r ) r->tn.op = FREE; /* don't clobber unary answer */
872: l = makety( l, p->tn.type, p->fn.cdim, p->fn.csiz );
873: p->tn.op = FREE;
874: return( l );
875: }
876:
877: chkpun(p)
878: register NODE *p;
879: {
880: /* checks p for the existance of a pun */
881: /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON,
882: ** or relational
883: */
884:
885: /* one case is when enumerations are used: this applies only to lint */
886: /* in the other case, one operand is a pointer, the other integer */
887: /* we check that this integer is in fact a constant zero... */
888: /* if it is, we redo the type of the 0 to match the other side */
889:
890: /* with ASSIGN, assignment of pointer to integer is illegal */
891: /* this falls out, because the LHS is never 0 */
892:
893: register NODE *q1, *q2;
894: register t1, t2;
895: register d1, d2;
896:
897: q1 = p->in.left;
898: q2 = p->in.right;
899: t1 = q1->in.type;
900: t2 = q2->in.type;
901:
902: if( t1==ENUMTY || t2==ENUMTY )
903: {
904: /* check for enumerations */
905: if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
906: {
907: uerror( "illegal comparison of enums" );
908: return;
909: }
910: if( t1==ENUMTY && t2==ENUMTY && q1->fn.csiz==q2->fn.csiz )
911: return;
912: werror( "enumeration type clash, operator %s", opst[p->in.op] );
913: return;
914: }
915:
916: if( ISPTR(t1) || ISARY(t1) )
917: { /* switch roles: q1 should be non-pointer */
918: q1 = q2;
919: q2 = p->in.left;
920: }
921:
922: if( !ISPTR(q1->in.type) && !ISARY(q1->in.type) )
923: {
924: if( q1->in.op == ICON && q1->tn.lval == 0 && q1->tn.rval == NONAME )
925: { /* make the 0 have the type of the other side */
926: q1->fn.type = q2->fn.type;
927: q1->fn.cdim = q2->fn.cdim;
928: q1->fn.csiz = q2->fn.type;
929: }
930: else
931: {
932: combo( "pointer/integer", p );
933: }
934: return;
935: }
936: else
937: { /* q1 and q2 still mean left and right */
938: d1 = q1->fn.cdim;
939: d2 = q2->fn.cdim;
940: for( ;; )
941: {
942: if( t1 == t2 )
943: {
944: ;
945: if(q1->fn.csiz!=q2->fn.csiz)
946: {
947: combo( "structure pointer", p );
948: }
949: return;
950: }
951: /****** LINT Change: Turn on only if LINT is to be used with this pcc2 ******/
952: /* /* complain about pointer casts if cflag is set
953: /* /* (this implies that pflag is set)
954: /* */
955: /* if (p->in.op == CAST)
956: /* {
957: /* if (ISPTR(tl) && ISPTR(t2))
958: /* {
959: /* werror(
960: /* "pointer casts may be troublesome");
961: /* return;
962: /* }
963: /* }
964: /****************************************************************************/
965: if( ISARY(t1) || ISPTR(t1) )
966: {
967: if( !ISARY(t2) && !ISPTR(t2) ) break;
968: if( ISARY(t1) && ISARY(t2) &&
969: dimtab[d1] != dimtab[d2] )
970: {
971: combo( "array size", p );
972: return;
973: }
974: if( ISARY(t1) ) ++d1;
975: if( ISARY(t2) ) ++d2;
976: }
977: else break;
978: t1 = DECREF(t1);
979: t2 = DECREF(t2);
980: }
981: combo( "pointer", p );
982: }
983: }
984:
985: combo( s, p )
986: char *s;
987: NODE *p;
988: {
989: char buf[100];
990: sprintf( buf, "illegal %s combination, op %s", s, opst[p->tn.op] );
991: werror( buf );
992: }
993:
994: NODE *
995: stref( p )
996: register NODE *p;
997: {
998: register TWORD t;
999: register d, s, dsc, align;
1000: register OFFSZ off;
1001: register struct symtab *q;
1002:
1003: /* make p->x */
1004: /* this is also used to reference automatic variables */
1005:
1006: q = &stab[p->in.right->tn.rval];
1007: p->in.right->in.op = FREE;
1008: p->in.op = FREE;
1009: p = pconvert( p->in.left );
1010:
1011: /* make p look like ptr to x */
1012:
1013: if( !ISPTR(p->in.type))
1014: {
1015: p->in.type = PTR+UNIONTY;
1016: }
1017:
1018: t = INCREF( q->stype );
1019: d = q->dimoff;
1020: s = q->sizoff;
1021:
1022: p = makety( p, t, d, s );
1023:
1024: /* compute the offset to be added */
1025:
1026: off = q->offset;
1027: dsc = q->sclass;
1028:
1029: if( dsc & FIELD )
1030: {
1031: /* normalize offset */
1032: switch(q->stype)
1033: {
1034:
1035: case CHAR:
1036: case UCHAR:
1037: align = ALCHAR;
1038: s = CHAR;
1039: break;
1040:
1041: case SHORT:
1042: case USHORT:
1043: align = ALSHORT;
1044: s = SHORT;
1045: break;
1046:
1047: case ENUMTY:
1048: case INT:
1049: case UNSIGNED:
1050: align = ALINT;
1051: s = INT;
1052: break;
1053:
1054: # ifdef LONGFIELDS
1055: case LONG:
1056: case ULONG:
1057: align = ALLONG;
1058: s = LONG;
1059: break;
1060: # endif
1061:
1062: default:
1063: cerror( "undefined bit field type" );
1064: }
1065: off = (off/align)*align;
1066: }
1067: if( off != 0 )
1068: p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
1069:
1070: p = buildtree( STAR, p, NIL );
1071:
1072: /* if field, build field info */
1073:
1074: if( dsc & FIELD )
1075: {
1076: p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
1077: p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
1078: }
1079:
1080: return( clocal(p) );
1081: }
1082:
1083: notlval(p)
1084: register NODE *p;
1085: {
1086:
1087: /* return 0 if p an lvalue, 1 otherwise */
1088:
1089: again:
1090: switch( p->in.op )
1091: {
1092:
1093: case FLD:
1094: p = p->in.left;
1095: goto again;
1096:
1097: case STAR:
1098: /* fix the &(a=b) bug, given that a and b are structures */
1099: if( p->in.left->in.op == STASG ) return( 1 );
1100: case NAME:
1101: case VAUTO:
1102: case VPARAM:
1103: case RNODE:
1104: case QNODE:
1105: case SNODE:
1106: if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
1107: case REG:
1108: return(0);
1109:
1110: default:
1111: return(1);
1112:
1113: }
1114:
1115: }
1116:
1117: NODE *
1118: bcon( i )
1119: {
1120: /* make a constant node with value i */
1121: register NODE *p;
1122:
1123: p = block( ICON, NIL, NIL, INT, 0, INT );
1124: p->tn.lval = i;
1125: p->tn.rval = NONAME;
1126: return( clocal(p) );
1127: }
1128:
1129: NODE *
1130: bpsize(p)
1131: register NODE *p;
1132: {
1133: return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
1134: }
1135:
1136: OFFSZ
1137: psize( p )
1138: register NODE *p;
1139: {
1140: /* p is a node of type pointer; psize returns the
1141: ** size of the thing pointed to
1142: */
1143:
1144: if( !ISPTR(p->in.type) )
1145: {
1146: uerror( "pointer required");
1147: return( SZINT );
1148: }
1149: /* note: no pointers to fields */
1150: return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
1151: }
1152:
1153: NODE *
1154: unconvert( p, q )
1155: register NODE *p, *q;
1156: {
1157: /* p is divided by the size of q */
1158: /* q had better have type pointer */
1159:
1160: # ifdef MYPDIV
1161: return( clocal( block( PDIV, p, bpsize(q), INT, 0, INT ) ) );
1162: # else
1163: p = makety( p, PTRTYPE, 0, PTRTYPE );
1164: p = clocal( buildtree( DIV, p, bpsize(q) ) );
1165:
1166: return( makety( p, PTRTYPE, 0, PTRTYPE ) );
1167: # endif
1168: }
1169:
1170: NODE *
1171: convert( p, f )
1172: register NODE *p;
1173: register f;
1174: {
1175: /* convert an operand of p
1176: ** f is either CVTL or CVTR
1177: ** operand has type int, and is converted by the size of the other side
1178: */
1179:
1180: register NODE *q, *r;
1181:
1182: if( f == CVTL )
1183: {
1184: q = p->in.left;
1185: r = bpsize( p->in.right );
1186: }
1187: else
1188: {
1189: q = p->in.right;
1190: r = bpsize( p->in.left );
1191: }
1192: # ifdef MYPMUL
1193: r = clocal( block( PMUL, q, r, PTRTYPE, 0, PTRTYPE ) );
1194: # else
1195: /* if PTRTYPE is defined, make q this size; then, the MUL will be */
1196: q = makety( q, PTRTYPE, 0, PTRTYPE );
1197: r = clocal( buildtree( MUL, q, r ) );
1198: # endif
1199: if( f == CVTL )
1200: p->in.left = r;
1201: else
1202: p->in.right = r;
1203: return(p);
1204:
1205: }
1206:
1207: econvert( p )
1208: register NODE *p;
1209: {
1210:
1211: /* change enums to ints, or appropriate types */
1212:
1213: register TWORD ty;
1214:
1215: if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY )
1216: {
1217: if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
1218: else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
1219: else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
1220: else ty = LONG;
1221: ty = ctype( ty );
1222: p->fn.csiz = ty;
1223: MODTYPE(p->in.type,ty);
1224: if( p->in.op == ICON && ty != LONG )
1225: p->in.type = p->fn.csiz = INT;
1226: }
1227: }
1228:
1229: NODE *
1230: pconvert( p )
1231: register NODE *p;
1232: {
1233: register TWORD t;
1234:
1235: /* if p should be changed into a pointer, do so */
1236: /* also, widen p so it can be used as an operand */
1237:
1238: if( ISARY( p->in.type) )
1239: {
1240: p->in.type = DECREF( p->in.type );
1241: ++p->fn.cdim;
1242: return( buildtree( UNARY AND, p, NIL ) );
1243: }
1244: if( ISFTN( p->in.type) )
1245: return( buildtree( UNARY AND, p, NIL ) );
1246:
1247: t = indtype( p->tn.type );
1248: if( t == p->tn.type ) return( p );
1249: if( p->tn.op == CONV && cbigger( p ) )
1250: {
1251: p->tn.type = p->fn.csiz = t;
1252: }
1253: else p = makety( p, t, 0, (int) t );
1254: return( p );
1255: }
1256:
1257: bigsize( t )
1258: TWORD t;
1259: {
1260: /* return a type size for t */
1261: switch( t )
1262: {
1263:
1264: case CHAR:
1265: case UCHAR:
1266: return( SZCHAR );
1267:
1268: case SHORT:
1269: case USHORT:
1270: return( SZSHORT );
1271:
1272: case VOID:
1273: case INT:
1274: case UNSIGNED:
1275: return( SZINT );
1276:
1277: case LONG:
1278: case ULONG:
1279: return( SZLONG );
1280:
1281: case FLOAT:
1282: return( SZLONG+1 ); /* must appear > long */
1283: case DOUBLE:
1284: return( SZLONG+2 );
1285:
1286: }
1287:
1288: if( ISPTR(t) || ISARY(t) ) return( SZPOINT );
1289: cerror( "bad bigsize: 0%o", t );
1290: /*NOTREACHED*/
1291: }
1292:
1293: cbigger( p )
1294: register NODE *p;
1295: {
1296: /* returns 1 if the conversion op p makes things bigger */
1297:
1298: if( p->tn.op != CONV ) cerror( "cbigger" );
1299: return( bigsize( p->tn.type ) > bigsize( p->in.left->tn.type ) );
1300: }
1301:
1302: NODE *
1303: oconvert(p)
1304: register NODE *p;
1305:
1306: {
1307: /* convert the result itself: used for pointer and unsigned */
1308: register TWORD t;
1309:
1310: switch(p->in.op)
1311: {
1312:
1313: case LE:
1314: case LT:
1315: case GE:
1316: case GT:
1317: t = p->in.left->in.type;
1318: if( ISUNSIGNED(t) || ISPTR(t) || ISARY(t) )
1319: {
1320: p->in.op += (ULE-LE);
1321: }
1322: else
1323: {
1324: t = p->in.right->in.type;
1325: if( ISUNSIGNED(t) || ISPTR(t) || ISARY(t) )
1326: {
1327: p->in.op += (ULE-LE);
1328: }
1329: }
1330: case EQ:
1331: case NE:
1332: case ULE:
1333: case ULT:
1334: case UGE:
1335: case UGT:
1336: return( p );
1337:
1338: case MINUS:
1339: return( unconvert( p, p->in.left ) );
1340: }
1341:
1342: cerror( "illegal oconvert: %d", p->in.op );
1343:
1344: return(p);
1345: }
1346:
1347: NODE *
1348: ptmatch(p)
1349: register NODE *p;
1350: {
1351:
1352: /* makes the operands of p agree; they are
1353: ** either pointers or integers, by this time
1354: */
1355: /* with MINUS, the sizes must be the same */
1356: /* with COLON, the types must be the same */
1357:
1358: register TWORD t1, t2, t;
1359: register o, d2, d, s2, s;
1360:
1361: o = p->in.op;
1362: t = t1 = p->in.left->in.type;
1363: t2 = p->in.right->in.type;
1364: d = p->in.left->fn.cdim;
1365: d2 = p->in.right->fn.cdim;
1366: s = p->in.left->fn.csiz;
1367: s2 = p->in.right->fn.csiz;
1368:
1369: switch( o )
1370: {
1371:
1372: case ASSIGN:
1373: case RETURN:
1374: case CAST:
1375: break;
1376:
1377: case MINUS:
1378: if( psize(p->in.left) != psize(p->in.right) )
1379: {
1380: uerror( "illegal pointer subtraction");
1381: }
1382: p->tn.type = p->fn.csiz = PTRTYPE;
1383: p->fn.cdim = 0;
1384: return( clocal(p) );
1385:
1386: case COLON:
1387: if( t1 != t2 ) uerror( "illegal types in :");
1388: break;
1389:
1390: default:
1391: if( !ISPTR(t1) )
1392: {
1393: t = t2;
1394: d = d2;
1395: s = s2;
1396: break;
1397: }
1398: if( !ISPTR(t2) )
1399: {
1400: break;
1401: }
1402:
1403: /* both are pointers */
1404: if( talign(t2,s2) < talign(t,s) )
1405: {
1406: t = t2;
1407: s = s2;
1408: }
1409: break;
1410: }
1411:
1412: p->in.left = makety( p->in.left, t, d, s );
1413: p->in.right = makety( p->in.right, t, d, s );
1414: if( !logop(o) )
1415: {
1416: p->in.type = t;
1417: p->fn.cdim = d;
1418: p->fn.csiz = s;
1419: }
1420:
1421: return(clocal(p));
1422: }
1423:
1424: int tdebug = 0;
1425:
1426: NODE *
1427: tymatch(p)
1428: register NODE *p;
1429: {
1430:
1431: /* satisfy the types of various arithmetic binary ops */
1432:
1433: /* rules are:
1434: ** if any float or doubles, make double
1435: ** if any longs, make long
1436: ** if any ints, make int
1437: ** if any shorts, make short
1438: ** otherwise, make char
1439: ** if either operand is unsigned, the result is...
1440: ** if a simple assignment, type = type of lhs
1441: ** if an asg. op, type = type of original lhs
1442: ** (under CONV, if any)
1443: */
1444:
1445: register o;
1446: register TWORD t1, t2;
1447: TWORD t, tu;
1448: register NODE *l, *r;
1449: int u;
1450:
1451: o = p->in.op;
1452:
1453: t1 = (l=p->in.left)->in.type;
1454: t2 = (r=p->in.right)->in.type;
1455:
1456: /* constants have a kind of "flexible" type */
1457:
1458: if( r->tn.op == ICON && r->tn.rval == NONAME &&
1459: (t1==CHAR || t1==UCHAR || t1==SHORT || t1==USHORT) )
1460: {
1461: /* if the constant retains its value when cast to the
1462: ** type of the lhs, assume it has the lhs type
1463: */
1464: if( r->tn.lval == ccast( r->tn.lval, t1 ) )
1465: {
1466: r->in.type = t2 = t1;
1467: r->fn.cdim = l->fn.cdim;
1468: r->fn.csiz = l->fn.csiz;
1469: }
1470: }
1471:
1472: /* this is the opposite case from the above (it is too early
1473: to assume that constants are on the right) */
1474:
1475: if( l->tn.op == ICON && l->tn.rval == NONAME &&
1476: (t2==CHAR || t2==UCHAR || t2==SHORT || t2==USHORT) )
1477: {
1478: /* if the constant retains its value when cast to the
1479: ** type of the rhs, assume it has the rhs type
1480: */
1481: if( l->tn.lval == ccast( l->tn.lval, t2 ) )
1482: {
1483: l->in.type = t1 = t2;
1484: l->fn.cdim = r->fn.cdim;
1485: l->fn.csiz = r->fn.csiz;
1486: }
1487: }
1488: if( (t1==VOID || t2==VOID) && o!=CAST )
1489: uerror("void type illegal in expression");
1490:
1491: u = 0;
1492: if( ISUNSIGNED(t1) )
1493: {
1494: u = 1;
1495: t1 = DEUNSIGN(t1);
1496: }
1497: if( ISUNSIGNED(t2) )
1498: {
1499: u = 1;
1500: t2 = DEUNSIGN(t2);
1501: }
1502:
1503: if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE;
1504: else if( t1==LONG || t2==LONG ) t = LONG;
1505: else if( t1==INT || t2==INT ) t = INT;
1506: else if( t1==SHORT || t2==SHORT ) t = SHORT;
1507: else t = CHAR;
1508:
1509: if( o == ASSIGN || o == CAST || o == RETURN )
1510: {
1511: tu = t1;
1512: if( o == RETURN )
1513: {
1514: if( tu==FLOAT ) tu = DOUBLE;
1515: else if( tu==CHAR || tu==SHORT ) tu = INT;
1516: }
1517: t = t1 = tu; /* t1 set to avoid lhs conversion */
1518: if( ISUNSIGNED(l->tn.type) ) u=1;
1519: else u=0;
1520: t2 = r->tn.type; /* back to reality... */
1521: }
1522: tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1523:
1524: if( tu != t1 ) p->in.left = makety( l, tu, 0, (int)tu );
1525: if( tu != t2 ) p->in.right = makety( r, tu, 0, (int)tu );
1526:
1527: if( !logop(o) ) /* the type of the node = type of the operation */
1528: {
1529: p->in.type = tu;
1530: p->fn.cdim = 0;
1531: p->fn.csiz = t;
1532: }
1533:
1534: if( asgop(o) && p->in.left->tn.op == CONV )
1535: {
1536: /* original, unconverted type */
1537: /* this will get rewritten to A = A op B, in most cases */
1538: /* if the op is an unsigned op, change the lhs to unsigned */
1539: l = p->in.left->in.left;
1540: tu = l->in.type;
1541: if( u && (UNSIGNABLE(tu)) ) tu = ENUNSIGN(tu);
1542: p->in.type = l->in.type = tu;
1543: p->fn.cdim = l->fn.cdim;
1544: p->fn.csiz = l->fn.csiz;
1545: }
1546:
1547: # ifndef NODBG
1548: if( tdebug )
1549: {
1550: printf( "tymatch(%o): %o '%s' %o => %o\n",p,t1,opst[o],t2,tu );
1551: e2print(p);
1552: }
1553: # endif
1554:
1555: return(p);
1556: }
1557:
1558: NODE *
1559: makety( p, t, d, s )
1560: register NODE *p;
1561: register TWORD t;
1562: register d,s;
1563: {
1564: /* make p into type t by inserting a conversion */
1565: register TWORD pt;
1566:
1567: pt = p->in.type;
1568:
1569: if( pt == ENUMTY && p->in.op == ICON )
1570: {
1571: econvert(p);
1572: pt = p->in.type;
1573: }
1574:
1575: if( ISARY(pt) || ISFTN(pt) )
1576: {
1577: p = pconvert( p );
1578: pt = p->in.type;
1579: }
1580:
1581: if( t == pt )
1582: {
1583: rew:
1584: p->fn.type = t;
1585: p->fn.cdim = d;
1586: p->fn.csiz = s;
1587: return( p );
1588: }
1589:
1590: if( t & TMASK )
1591: {
1592: /* non-simple type */
1593: if( ISPTR(pt)
1594: # ifdef TWOPTRS
1595: && TWOPTRS(t) == TWOPTRS(pt)
1596: # endif
1597: )
1598: {
1599: /* don't generate CONV: just rewrite type */
1600: goto rew;
1601: }
1602:
1603: return( block( CONV, p, NIL, t, d, s ) );
1604: }
1605:
1606: if( p->in.op == ICON && p->tn.rval==NONAME )
1607: {
1608: if( t==DOUBLE||t==FLOAT )
1609: {
1610: p->in.op = FCON;
1611: if( ISUNSIGNED(pt) )
1612: {
1613: p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
1614: }
1615: else
1616: {
1617: p->fpn.dval = p->tn.lval;
1618: }
1619: goto rew;
1620: }
1621: p->tn.lval = ccast( p->tn.lval, t );
1622: goto rew;
1623: }
1624: return( block( CONV, p, NIL, t, d, s ) );
1625: }
1626:
1627: NODE *
1628: block( o, l, r, t, d, s )
1629: register NODE *l, *r;
1630: register TWORD t;
1631: register o,d,s;
1632: {
1633:
1634: register NODE *p;
1635:
1636: p = talloc();
1637: p->in.op = o;
1638: p->in.left = l;
1639: p->in.right = r;
1640: p->in.type = t;
1641: p->fn.cdim = d;
1642: p->fn.csiz = s;
1643:
1644: /* for really heavy debugging
1645: printf( "block( %s, %d, %d, 0%o, %d, %d ) yields %d\n",
1646: opst[o], l-node, r-node, t, d, s, p-node );
1647: */
1648:
1649: return(p);
1650: }
1651:
1652: icons(p)
1653: register NODE *p;
1654: {
1655: /* if p is an integer constant, return its value */
1656: register val;
1657:
1658: if( p->in.op != ICON )
1659: {
1660: uerror( "constant expected");
1661: val = 1;
1662: }
1663: else
1664: {
1665: val = p->tn.lval;
1666: if( val != p->tn.lval )
1667: uerror( "constant too big for cross-compiler" );
1668: }
1669: tfree( p );
1670: return(val);
1671: }
1672:
1673: /* the intent of this table is to examine the
1674: ** operators, and to check them for
1675: ** correctness.
1676: **
1677: ** The table is searched for the op and the
1678: ** modified type (where this is one of the
1679: ** types INT (includes char and short), LONG,
1680: ** DOUBLE (includes FLOAT), and POINTER
1681: **
1682: ** The default action is to make the node type integer
1683: **
1684: ** The actions taken include:
1685: ** PUN check for puns
1686: ** CVTL convert the left operand
1687: ** CVTR convert the right operand
1688: ** TYPL the type is determined by the left operand
1689: ** TYPR the type is determined by the right operand
1690: ** TYMATCH force type of left and right to match, by inserting conversions
1691: ** PTMATCH like TYMATCH, but for pointers
1692: ** LVAL left operand must be lval
1693: ** CVTO convert the op
1694: ** NCVT do not convert the operands
1695: ** OTHER handled by code
1696: ** NCVTR convert the left operand, not the right...
1697: **
1698: */
1699:
1700: # define MINT 01 /* integer */
1701: # define MDBI 02 /* integer or double */
1702: # define MSTR 04 /* structure */
1703: # define MPTR 010 /* pointer */
1704: # define MPTI 020 /* pointer or integer */
1705: # define MENU 040 /* enumeration variable or member */
1706:
1707: opact( p )
1708: register NODE *p;
1709: {
1710: register mt12, mt1, mt2, o;
1711:
1712: mt12 = 0;
1713:
1714: switch( optype(o=p->in.op) )
1715: {
1716:
1717: case BITYPE:
1718: mt12=mt2 = moditype( p->in.right->in.type );
1719: case UTYPE:
1720: mt12 &= (mt1 = moditype( p->in.left->in.type ));
1721:
1722: }
1723:
1724: switch( o )
1725: {
1726:
1727: case NAME :
1728: case STRING :
1729: case ICON :
1730: case FCON :
1731: case CALL :
1732: case UNARY CALL:
1733: case STAR:
1734: {
1735: return( OTHER );
1736: }
1737: case UNARY MINUS:
1738: if( mt1 & MDBI ) return( TYPL );
1739: break;
1740:
1741: case COMPL:
1742: if( mt1 & MINT ) return( TYPL );
1743: break;
1744:
1745: case UNARY AND:
1746: {
1747: return( NCVT+OTHER );
1748: }
1749: case INIT:
1750: case CM:
1751: return( 0 );
1752: case NOT:
1753: case CBRANCH:
1754: case ANDAND:
1755: case OROR:
1756: return( NCVT+OTHER );
1757:
1758: case MUL:
1759: case DIV:
1760: if( mt12 & MDBI ) return( TYMATCH );
1761: break;
1762:
1763: case MOD:
1764: case AND:
1765: case OR:
1766: case ER:
1767: case LS:
1768: case RS:
1769: if( mt12 & MINT ) return( TYMATCH );
1770: break;
1771:
1772: case EQ:
1773: case NE:
1774: case LT:
1775: case LE:
1776: case GT:
1777: case GE:
1778: if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN );
1779: if( mt12 & MDBI ) return( TYMATCH+CVTO );
1780: else if( mt12 & MPTR ) return( PTMATCH+PUN+CVTO );
1781: else if( mt12 & MPTI ) return( PTMATCH+PUN+CVTO );
1782: else break;
1783:
1784: case QUEST:
1785: case COMOP:
1786: return( TYPR+NCVTR );
1787:
1788: case STREF:
1789: return( NCVTR+OTHER );
1790:
1791: case COLON:
1792: if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
1793: else if( mt12 & MDBI ) return( TYMATCH );
1794: else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1795: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1796: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1797: else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1798: break;
1799:
1800: case ASSIGN:
1801: case RETURN:
1802: if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1803: case CAST:
1804: if(o==CAST && mt1==0)return(TYPL+TYMATCH);
1805: if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
1806: else if( (mt1&MENU)||(mt2&MENU) )
1807: {
1808: return( LVAL+NCVT+TYPL+PTMATCH+PUN );
1809: }
1810: else if( mt12 == 0 ) break;
1811: else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
1812: else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1813: break;
1814:
1815: case ASG MUL:
1816: case ASG DIV:
1817: if( mt12 & MDBI ) return( LVAL+TYMATCH );
1818: break;
1819:
1820: case ASG MOD:
1821: case ASG AND:
1822: case ASG OR:
1823: case ASG ER:
1824: case ASG LS:
1825: case ASG RS:
1826: if( mt12 & MINT ) return( LVAL+TYMATCH );
1827: break;
1828:
1829: case ASG PLUS:
1830: case ASG MINUS:
1831: case INCR:
1832: case DECR:
1833: if( mt12 & MDBI ) return( TYMATCH+LVAL );
1834: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1835: break;
1836:
1837: case MINUS:
1838: if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1839: if( mt2 & MPTR ) break;
1840: case PLUS:
1841: if( mt12 & MDBI ) return( TYMATCH );
1842: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1843: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1844:
1845: /* special operators */
1846: case UOP0:
1847: case UOP1:
1848: case UOP2:
1849: case UOP3:
1850: case UOP4:
1851: case UOP5:
1852: case UOP6:
1853: case UOP7:
1854: case UOP8:
1855: case UOP9:
1856: return( TYPL );
1857: }
1858: uerror( "operands of %s have incompatible types", opst[o] );
1859: return( NCVT );
1860: }
1861:
1862: moditype( ty )
1863: register TWORD ty;
1864: {
1865:
1866: switch( ty )
1867: {
1868:
1869: case UNDEF:
1870: case VOID:
1871: return(0); /* type is void */
1872: case ENUMTY:
1873: return( MINT|MPTI|MDBI ); /* bnl 11/18/85 */
1874: case MOETY:
1875: return( MENU );
1876:
1877: case STRTY:
1878: case UNIONTY:
1879: return( MSTR );
1880:
1881: case CHAR:
1882: case SHORT:
1883: case UCHAR:
1884: case USHORT:
1885: return( MINT|MPTI|MDBI );
1886:
1887: case UNSIGNED:
1888: case ULONG:
1889: case INT:
1890: case LONG:
1891: return( MINT|MDBI|MPTI );
1892:
1893: case FLOAT:
1894: case DOUBLE:
1895: return( MDBI );
1896:
1897: default:
1898: return( MPTR|MPTI );
1899: }
1900: }
1901:
1902: # ifndef MYCCAST
1903: CONSZ
1904: ccast( v, t )
1905: register CONSZ v;
1906: register TWORD t;
1907: {
1908: /* cast value v into simple type t */
1909: /* must be done as it would be on the target machine */
1910:
1911: switch( t )
1912: {
1913:
1914: case CHAR:
1915: # ifdef CHSIGN
1916: if( v&ONEBIT(SZCHAR-1) )
1917: {
1918: return( v | ~BITMASK(SZCHAR) );
1919: }
1920: # endif
1921: case UCHAR:
1922: return( v & BITMASK(SZCHAR) );
1923:
1924: case SHORT:
1925: if( v&ONEBIT(SZSHORT-1) )
1926: {
1927: return( v | ~BITMASK(SZSHORT) );
1928: }
1929: case USHORT:
1930: return( v & BITMASK(SZSHORT) );
1931:
1932: case INT:
1933: if( v&ONEBIT(SZINT-1) )
1934: {
1935: return( v | ~BITMASK(SZINT) );
1936: }
1937: case UNSIGNED:
1938: return( v & BITMASK(SZINT) );
1939:
1940: default:
1941: return( v );
1942: }
1943: }
1944: # endif
1945:
1946:
1947: NODE *
1948: doszof( p )
1949: register NODE *p;
1950: {
1951: /* do sizeof p */
1952: register i;
1953:
1954: /* whatever is the meaning of this if it is a bitfield? */
1955: i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1956:
1957: tfree(p);
1958: if( i <= 0 ) werror( "sizeof returns 0" );
1959: p = bcon(i);
1960: p->tn.type = UNSIGNED; /* damn dmr anyhow! */
1961: return( p );
1962: }
1963:
1964: # ifndef NODBG
1965: eprint(p)
1966: NODE *p;
1967: {
1968: printf("\n++++++++\n");
1969: e1print(p,"T");
1970: printf("---------\n");
1971: }
1972: e1print( p ,s)
1973: register NODE *p;
1974: char *s;
1975: {
1976: register ty, d;
1977: static down = 0;
1978:
1979: ty = optype( p->tn.op );
1980:
1981: if( ty == BITYPE )
1982: {
1983: ++down;
1984: e1print( p->in.right ,"R");
1985: --down;
1986: }
1987:
1988: for( d=down; d>1; d -= 2 ) printf( "\t" );
1989: if( d ) printf( " " );
1990:
1991: printf("%s=%d) %s, ", s, (int) (p-node), opst[p->in.op] );
1992: if( ty == LTYPE )
1993: {
1994: printf( "lval=%ld", p->tn.lval );
1995: printf( ", rval=%d, ", p->tn.rval );
1996: }
1997: printf("type=");
1998: tprint( p->in.type );
1999: printf( ", dim=%d, siz=%d\n", p->fn.cdim, p->fn.csiz );
2000: if( ty != LTYPE )
2001: {
2002: ++down;
2003: e1print( p->in.left ,"L");
2004: --down;
2005: }
2006: }
2007:
2008: tprint( t )
2009: register TWORD t;
2010: {
2011: /* output a nice description of the type of t */
2012: static char * tnames[] =
2013: {
2014: "undef",
2015: "farg",
2016: "char",
2017: "short",
2018: "int",
2019: "long",
2020: "float",
2021: "double",
2022: "strty",
2023: "unionty",
2024: "enumty",
2025: "moety",
2026: "uchar",
2027: "ushort",
2028: "unsigned",
2029: "ulong",
2030: "?", "?"
2031: };
2032:
2033: for(;; t = DECREF(t) )
2034: {
2035: if( ISPTR(t) ) printf( "PTR " );
2036: else if( ISFTN(t) ) printf( "FTN " );
2037: else if( ISARY(t) ) printf( "ARY " );
2038: else
2039: {
2040: printf( "%s", tnames[t] );
2041: return;
2042: }
2043: }
2044: }
2045: # endif
2046:
2047: # ifndef MYLOCCTR
2048: locctr(l)
2049: register l;
2050: {
2051: register temp, lt;
2052: /* look in locnames; print out the location counter name */
2053: /* null means use the next; all null, don't print */
2054: for( lt=l; lt<=STRNG && !locnames[lt]; ++lt )
2055: {
2056: /* EMPTY */
2057: }
2058: if( lt == curloc ) return( lt );
2059: temp = curloc;
2060: if( lt > STRNG ) lt = l;
2061: else printf( locnames[lt] );
2062: curloc = lt;
2063: return( temp );
2064: }
2065: # endif
2066:
2067: # ifndef NOFLOAT
2068:
2069: prtdcon( p )
2070: register NODE *p;
2071: {
2072: register i;
2073: register TWORD t;
2074:
2075: if( p->in.op == FCON )
2076: {
2077: locctr( DATA );
2078: t = p->tn.type;
2079: defalign( t==DOUBLE?ALDOUBLE:ALFLOAT );
2080: deflab( i = getlab() );
2081: fincode( p->fpn.dval, t==DOUBLE?SZDOUBLE:SZFLOAT );
2082: p->tn.lval = 0;
2083: p->tn.rval = -i;
2084: p->in.op = NAME;
2085: }
2086: if( (i = optype(p->in.op)) == BITYPE ) prtdcon( p->in.right );
2087: if( i != LTYPE ) prtdcon( p->in.left );
2088: }
2089: # endif
2090:
2091: # ifndef MYLABELS
2092: getlab()
2093: {
2094: static crslab = 10;
2095: return( ++crslab );
2096: }
2097: # endif
2098:
2099: int edebug = 0;
2100: ecomp( p )
2101: register NODE *p;
2102: {
2103: # ifndef NODBG
2104: if( edebug ) eprint(p);
2105: # endif
2106: if( !reached )
2107: {
2108: werror( "statement not reached" );
2109: reached = 1;
2110: }
2111: # ifdef CLOCAL
2112: p = clocal(p);
2113: # endif
2114: p = optim(p);
2115: # ifndef NOFLOAT
2116: prtdcon(p);
2117: # endif
2118: locctr( PROG );
2119: ecode(p);
2120: tfree(p);
2121: }
2122:
2123: # ifndef MYECODE
2124: ecode( p )
2125: register NODE *p;
2126: {
2127: /* standard version of writing the tree nodes */
2128: if( nerrors ) return;
2129: # ifdef SDB
2130: sdbline();
2131: # endif
2132: p2tree( p );
2133: p2compile( p );
2134: }
2135: # endif
2136:
2137: # ifndef MYPRTREE
2138:
2139: # ifndef RNODNAME
2140: # define RNODNAME LABFMT
2141: # endif
2142:
2143: p2tree(p)
2144: register NODE *p;
2145: {
2146: register ty;
2147: register NODE *l;
2148: register o;
2149: char temp[32]; /* place to dump label stuff */
2150:
2151: # ifdef MYP2TREE
2152: MYP2TREE(p); /* local action can be taken here; then return... */
2153: # endif
2154:
2155: /* this routine sits painfully between pass1 and pass2 */
2156: ty = optype(o=p->in.op);
2157: p->tn.goal = 0; /* an illegal goal, just to clear it out */
2158: p->tn.type = ttype( p->tn.type ); /* type gets second-pass (bits) */
2159:
2160: switch( o )
2161: {
2162:
2163: case TEMP:
2164: case NAME:
2165: case ICON:
2166: case VAUTO:
2167: case VPARAM:
2168: if( p->tn.rval == NONAME )
2169: p->in.name = (char *) 0;
2170: else if( p->tn.rval >= 0 )
2171: {
2172: /* copy name from exname */
2173: register char *cp;
2174: cp = exname( stab[p->tn.rval].sname );
2175: p->in.name = tstr( cp );
2176: }
2177: else if( p->tn.rval == - strftn )
2178: {
2179: sprintf( temp, RNODNAME, -p->tn.rval );
2180: p->in.name = tstr( temp );
2181: }
2182: else
2183: {
2184: sprintf( temp, LABFMT, -p->tn.rval );
2185: p->in.name = tstr( temp );
2186: }
2187: break;
2188:
2189: case STARG:
2190: case STASG:
2191: case STCALL:
2192: case UNARY STCALL:
2193: /* set up size parameters */
2194: l = p->in.left;
2195: p->stn.stsize = tsize(STRTY,l->fn.cdim,l->fn.csiz);
2196: p->stn.stalign = talign(STRTY,l->fn.csiz);
2197: break;
2198:
2199: /* this should do something only if temporary regs are
2200: /* built into the tree by machine-dependent actions */
2201: case REG:
2202: rbusy( p->tn.rval, p->in.type );
2203: default:
2204: p->in.name = (char *) 0;
2205: }
2206:
2207: if( ty != LTYPE ) p2tree( p->in.left );
2208: if( ty == BITYPE ) p2tree( p->in.right );
2209: }
2210:
2211: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.