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