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