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