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