|
|
1.1 root 1: #ifndef lint
2: static char *sccsid ="@(#)trees.c 4.37 (Berkeley) 6/18/90";
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: void
598: fpe() {
599: if (fpe_count < 0)
600: cerror("floating point exception");
601: ++fpe_count;
602: longjmp(gotfpe, 1);
603: }
604:
605: /*
606: * Rewrite arguments in a function call.
607: * Structure arguments are massaged, single
608: * precision floating point constants are
609: * cast to double (to eliminate convert code).
610: */
611: NODE *
612: fixargs( p ) register NODE *p; {
613: int o = p->in.op;
614:
615: if( o == CM ){
616: p->in.left = fixargs( p->in.left );
617: p->in.right = fixargs( p->in.right );
618: return( p );
619: }
620:
621: if( p->in.type == STRTY || p->in.type == UNIONTY ){
622: p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
623: p->in.left = buildtree( UNARY AND, p->in.left, NIL );
624: p = clocal(p);
625: }
626: else if( o == FCON )
627: p = makety(p, DOUBLE, 0, 0);
628: return( p );
629: }
630:
631: chkstr( i, j, type ) TWORD type; {
632: /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
633: /* i has been checked to contain a MOS or MOU */
634: /* j is the index in dimtab of the members... */
635: int k, kk;
636:
637: extern int ddebug;
638:
639: # ifndef BUG1
640: #ifndef FLEXNAMES
641: if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
642: #else
643: if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
644: #endif
645: # endif
646: if( (k = j) < 0 ) uerror( "undefined structure or union" );
647: else {
648: for( ; (kk = dimtab[k] ) >= 0; ++k ){
649: if( kk >= SYMTSZ ){
650: cerror( "gummy structure" );
651: return(1);
652: }
653: if( kk == i ) return( 1 );
654: switch( stab[kk].stype ){
655:
656: case STRTY:
657: case UNIONTY:
658: if( type == STRTY ) continue; /* no recursive looking for strs */
659: if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
660: if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */
661: werror(
662: #ifndef FLEXNAMES
663: "illegal member use: perhaps %.8s.%.8s?",
664: #else
665: "illegal member use: perhaps %s.%s?",
666: #endif
667: stab[kk].sname, stab[i].sname );
668: return(1);
669: }
670: }
671: }
672: }
673: return( 0 );
674: }
675:
676: conval( p, o, q ) register NODE *p, *q; {
677: /* apply the op o to the lval part of p; if binary, rhs is val */
678: /* works only on integer constants */
679: NODE *r;
680: int i, u;
681: CONSZ val;
682: TWORD utype;
683:
684: val = q->tn.lval;
685: u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
686: if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
687:
688: if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
689: if( q->tn.rval != NONAME && o!=PLUS ) return(0);
690: if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
691:
692: /* usual type conversions -- handle casts of constants */
693: #define ISLONG(t) ((t) == LONG || (t) == ULONG)
694: if (ISLONG(p->in.type) || ISLONG(q->in.type))
695: utype = u ? ULONG : LONG;
696: else
697: utype = u ? UNSIGNED : INT;
698: if( !ISPTR(p->in.type) && p->in.type != utype )
699: p = makety(p, utype, 0, (int)utype);
700: if( q->in.type != utype )
701: q = makety(q, utype, 0, (int)utype);
702:
703: switch( o ){
704:
705: case PLUS:
706: p->tn.lval += val;
707: if( p->tn.rval == NONAME ){
708: p->tn.rval = q->tn.rval;
709: p->in.type = q->in.type;
710: }
711: break;
712: case MINUS:
713: p->tn.lval -= val;
714: break;
715: case MUL:
716: p->tn.lval *= val;
717: break;
718: case DIV:
719: if( val == 0 ) uerror( "division by 0" );
720: else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
721: else p->tn.lval /= val;
722: break;
723: case MOD:
724: if( val == 0 ) uerror( "division by 0" );
725: else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
726: else p->tn.lval %= val;
727: break;
728: case AND:
729: p->tn.lval &= val;
730: break;
731: case OR:
732: p->tn.lval |= val;
733: break;
734: case ER:
735: p->tn.lval ^= val;
736: break;
737: case LS:
738: i = val;
739: p->tn.lval = p->tn.lval << i;
740: break;
741: case RS:
742: i = val;
743: if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
744: else p->tn.lval = p->tn.lval >> i;
745: break;
746:
747: case UNARY MINUS:
748: p->tn.lval = - p->tn.lval;
749: break;
750: case COMPL:
751: p->tn.lval = ~p->tn.lval;
752: break;
753: case NOT:
754: p->tn.lval = !p->tn.lval;
755: break;
756: case LT:
757: p->tn.lval = p->tn.lval < val;
758: break;
759: case LE:
760: p->tn.lval = p->tn.lval <= val;
761: break;
762: case GT:
763: p->tn.lval = p->tn.lval > val;
764: break;
765: case GE:
766: p->tn.lval = p->tn.lval >= val;
767: break;
768: case ULT:
769: p->tn.lval = p->tn.lval < (unsigned) val;
770: break;
771: case ULE:
772: p->tn.lval = p->tn.lval <= (unsigned) val;
773: break;
774: case UGT:
775: p->tn.lval = p->tn.lval > (unsigned) val;
776: break;
777: case UGE:
778: p->tn.lval = p->tn.lval >= (unsigned) val;
779: break;
780: case EQ:
781: p->tn.lval = p->tn.lval == val;
782: break;
783: case NE:
784: p->tn.lval = p->tn.lval != val;
785: break;
786: default:
787: return(0);
788: }
789: return(1);
790: }
791:
792: chkpun(p) register NODE *p; {
793:
794: /* checks p for the existance of a pun */
795:
796: /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
797:
798: /* one case is when enumerations are used: this applies only to lint */
799: /* in the other case, one operand is a pointer, the other integer type */
800: /* we check that this integer is in fact a constant zero... */
801:
802: /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
803: /* this falls out, because the LHS is never 0 */
804:
805: register NODE *q;
806: register t1, t2;
807: register d1, d2;
808: int ref1, ref2;
809:
810: t1 = p->in.left->in.type;
811: t2 = p->in.right->in.type;
812:
813: if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
814: /* rob pike says this is obnoxious...
815: if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
816: werror( "comparison of enums" ); */
817: if( t1==ENUMTY && t2==ENUMTY ) {
818: if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
819: werror( "enumeration type clash, operator %s", opst[p->in.op] );
820: return;
821: }
822: if ( t1 == ENUMTY ) t1 = INT;
823: if ( t2 == ENUMTY ) t2 = INT;
824: }
825:
826: ref1 = ISPTR(t1) || ISARY(t1);
827: ref2 = ISPTR(t2) || ISARY(t2);
828:
829: if( ref1 ^ ref2 ){
830: if( ref1 ) q = p->in.right;
831: else q = p->in.left;
832: if( q->in.op != ICON || q->tn.lval != 0 ){
833: werror( "illegal combination of pointer and integer, op %s",
834: opst[p->in.op] );
835: }
836: }
837: else if( ref1 ){
838: if( t1 == t2 ) {
839: if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
840: werror( "illegal structure pointer combination" );
841: return;
842: }
843: d1 = p->in.left->fn.cdim;
844: d2 = p->in.right->fn.cdim;
845: for( ;; ){
846: if( ISARY(t1) ){
847: if( dimtab[d1] != dimtab[d2] ){
848: werror( "illegal array size combination" );
849: return;
850: }
851: ++d1;
852: ++d2;
853: }
854: else if( !ISPTR(t1) ) break;
855: t1 = DECREF(t1);
856: }
857: }
858: else if( t1 != INCREF(UNDEF) && t2 != INCREF(UNDEF) )
859: werror( "illegal pointer combination" );
860: }
861:
862: }
863:
864: NODE *
865: stref( p ) register NODE *p; {
866:
867: TWORD t;
868: int d, s, dsc, align;
869: OFFSZ off;
870: register struct symtab *q;
871:
872: /* make p->x */
873: /* this is also used to reference automatic variables */
874:
875: q = &stab[p->in.right->tn.rval];
876: p->in.right->in.op = FREE;
877: p->in.op = FREE;
878: p = pconvert( p->in.left );
879:
880: /* make p look like ptr to x */
881:
882: if( !ISPTR(p->in.type)){
883: p->in.type = PTR+UNIONTY;
884: }
885:
886: t = INCREF( q->stype );
887: d = q->dimoff;
888: s = q->sizoff;
889:
890: p = makety( p, t, d, s );
891:
892: /* compute the offset to be added */
893:
894: off = q->offset;
895: dsc = q->sclass;
896:
897: if( dsc & FIELD ) { /* normalize offset */
898: align = ALINT;
899: s = INT;
900: off = (off/align)*align;
901: }
902: if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
903:
904: p = buildtree( UNARY MUL, p, NIL );
905:
906: /* if field, build field info */
907:
908: if( dsc & FIELD ){
909: p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
910: p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
911: }
912:
913: return( clocal(p) );
914: }
915:
916: notlval(p) register NODE *p; {
917:
918: /* return 0 if p an lvalue, 1 otherwise */
919:
920: again:
921:
922: switch( p->in.op ){
923:
924: case FLD:
925: p = p->in.left;
926: goto again;
927:
928: case UNARY MUL:
929: /* fix the &(a=b) bug, given that a and b are structures */
930: if( p->in.left->in.op == STASG ) return( 1 );
931: /* and the f().a bug, given that f returns a structure */
932: if( p->in.left->in.op == UNARY STCALL ||
933: p->in.left->in.op == STCALL ) return( 1 );
934: case NAME:
935: case OREG:
936: if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
937: case REG:
938: return(0);
939:
940: default:
941: return(1);
942:
943: }
944:
945: }
946:
947: NODE *
948: bcon( i ){ /* make a constant node with value i */
949: register NODE *p;
950:
951: p = block( ICON, NIL, NIL, INT, 0, INT );
952: p->tn.lval = i;
953: p->tn.rval = NONAME;
954: return( clocal(p) );
955: }
956:
957: NODE *
958: bpsize(p) register NODE *p; {
959: return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
960: }
961:
962: OFFSZ
963: psize( p ) NODE *p; {
964: /* p is a node of type pointer; psize returns the
965: size of the thing pointed to */
966:
967: if( !ISPTR(p->in.type) ){
968: uerror( "pointer required");
969: return( SZINT );
970: }
971: /* note: no pointers to fields */
972: return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
973: }
974:
975: NODE *
976: convert( p, f ) register NODE *p; {
977: /* convert an operand of p
978: f is either CVTL or CVTR
979: operand has type int, and is converted by the size of the other side
980: */
981:
982: register NODE *q, *r;
983:
984: q = (f==CVTL)?p->in.left:p->in.right;
985:
986: r = block( PMCONV,
987: q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
988: r = clocal(r);
989: if( f == CVTL )
990: p->in.left = r;
991: else
992: p->in.right = r;
993: return(p);
994:
995: }
996:
997: #ifndef econvert
998: econvert( p ) register NODE *p; {
999:
1000: /* change enums to ints, or appropriate types */
1001:
1002: register TWORD ty;
1003:
1004: if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
1005: if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
1006: else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
1007: else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
1008: else ty = LONG;
1009: ty = ctype( ty );
1010: p->fn.csiz = ty;
1011: MODTYPE(p->in.type,ty);
1012: if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
1013: }
1014: }
1015: #endif
1016:
1017: NODE *
1018: pconvert( p ) register NODE *p; {
1019:
1020: /* if p should be changed into a pointer, do so */
1021:
1022: if( ISARY( p->in.type) ){
1023: p->in.type = DECREF( p->in.type );
1024: ++p->fn.cdim;
1025: return( buildtree( UNARY AND, p, NIL ) );
1026: }
1027: if( ISFTN( p->in.type) )
1028: return( buildtree( UNARY AND, p, NIL ) );
1029:
1030: return( p );
1031: }
1032:
1033: NODE *
1034: oconvert(p) register NODE *p; {
1035: /* convert the result itself: used for pointer and unsigned */
1036:
1037: switch(p->in.op) {
1038:
1039: case LE:
1040: case LT:
1041: case GE:
1042: case GT:
1043: if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE);
1044: case EQ:
1045: case NE:
1046: return( p );
1047:
1048: case MINUS:
1049: return( clocal( block( PVCONV,
1050: p, bpsize(p->in.left), INT, 0, INT ) ) );
1051: }
1052:
1053: cerror( "illegal oconvert: %d", p->in.op );
1054:
1055: return(p);
1056: }
1057:
1058: NODE *
1059: ptmatch(p) register NODE *p; {
1060:
1061: /* makes the operands of p agree; they are
1062: either pointers or integers, by this time */
1063: /* with MINUS, the sizes must be the same */
1064: /* with COLON, the types must be the same */
1065:
1066: TWORD t1, t2, t;
1067: int o, d2, d, s2, s;
1068:
1069: o = p->in.op;
1070: t = t1 = p->in.left->in.type;
1071: t2 = p->in.right->in.type;
1072: d = p->in.left->fn.cdim;
1073: d2 = p->in.right->fn.cdim;
1074: s = p->in.left->fn.csiz;
1075: s2 = p->in.right->fn.csiz;
1076:
1077: switch( o ){
1078:
1079: case ASSIGN:
1080: case RETURN:
1081: case CAST:
1082: { break; }
1083:
1084: case MINUS:
1085: { if( psize(p->in.left) != psize(p->in.right) ){
1086: uerror( "illegal pointer subtraction");
1087: }
1088: break;
1089: }
1090: case COLON:
1091: { if( t1 != t2 ) uerror( "illegal types in :");
1092: break;
1093: }
1094: default: /* must work harder: relationals or comparisons */
1095:
1096: if( !ISPTR(t1) ){
1097: t = t2;
1098: d = d2;
1099: s = s2;
1100: break;
1101: }
1102: if( !ISPTR(t2) ){
1103: break;
1104: }
1105:
1106: /* both are pointers */
1107: if( talign(t2,s2) < talign(t,s) ){
1108: t = t2;
1109: s = s2;
1110: }
1111: break;
1112: }
1113:
1114: p->in.left = makety( p->in.left, t, d, s );
1115: p->in.right = makety( p->in.right, t, d, s );
1116: if( o!=MINUS && !logop(o) ){
1117:
1118: p->in.type = t;
1119: p->fn.cdim = d;
1120: p->fn.csiz = s;
1121: }
1122:
1123: return(clocal(p));
1124: }
1125:
1126: int tdebug = 0;
1127:
1128: NODE *
1129: tymatch(p) register NODE *p; {
1130:
1131: /* satisfy the types of various arithmetic binary ops */
1132:
1133: /* rules are:
1134: if assignment, type of LHS
1135: if any float or doubles, make double
1136: if any longs, make long
1137: otherwise, make int
1138: if either operand is unsigned, the result is...
1139: */
1140:
1141: register TWORD t1, t2, t, tu;
1142: register o, u;
1143:
1144: o = p->in.op;
1145:
1146: t1 = p->in.left->in.type;
1147: t2 = p->in.right->in.type;
1148: if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
1149: uerror("void type illegal in expression");
1150:
1151: u = 0;
1152: if( ISUNSIGNED(t1) ){
1153: u = 1;
1154: t1 = DEUNSIGN(t1);
1155: }
1156: if( ISUNSIGNED(t2) ){
1157: u = 1;
1158: t2 = DEUNSIGN(t2);
1159: }
1160:
1161: if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
1162: if( t2 == CHAR || t2 == SHORT ) t2 = INT;
1163:
1164: #ifdef SPRECC
1165: if( t1 == DOUBLE || t2 == DOUBLE )
1166: t = DOUBLE;
1167: else if( t1 == FLOAT || t2 == FLOAT )
1168: t = FLOAT;
1169: #else
1170: if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
1171: t = DOUBLE;
1172: #endif
1173: else if( t1==LONG || t2==LONG ) t = LONG;
1174: else t = INT;
1175:
1176: if( o == ASSIGN || o == CAST || o == RETURN )
1177: {
1178: tu = p->in.left->in.type;
1179: t = t1;
1180: }
1181: else {
1182: tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1183: }
1184:
1185: /* because expressions have values that are at least as wide
1186: as INT or UNSIGNED, the only conversions needed
1187: are those involving FLOAT/DOUBLE, and those
1188: from LONG to INT and ULONG to UNSIGNED */
1189:
1190: if( (t != t1 || (u && !ISUNSIGNED(p->in.left->in.type))) && ! asgop(o) )
1191: p->in.left = makety( p->in.left, tu, 0, (int)tu );
1192:
1193: if( t != t2 || (u && !ISUNSIGNED(p->in.right->in.type)) || o==CAST)
1194: if ( tu == ENUMTY ) {/* always asgop */
1195: p->in.right = makety( p->in.right, INT, 0, INT );
1196: p->in.right->in.type = tu;
1197: p->in.right->fn.cdim = p->in.left->fn.cdim;
1198: p->in.right->fn.csiz = p->in.left->fn.csiz;
1199: }
1200: else
1201: p->in.right = makety( p->in.right, tu, 0, (int)tu );
1202:
1203: if( asgop(o) ){
1204: p->in.type = p->in.left->in.type;
1205: p->fn.cdim = p->in.left->fn.cdim;
1206: p->fn.csiz = p->in.left->fn.csiz;
1207: }
1208: else if( !logop(o) ){
1209: p->in.type = tu;
1210: p->fn.cdim = 0;
1211: p->fn.csiz = t;
1212: }
1213:
1214: # ifndef BUG1
1215: if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
1216: # endif
1217:
1218: return(p);
1219: }
1220:
1221: NODE *
1222: makety( p, t, d, s ) register NODE *p; TWORD t; {
1223: /* make p into type t by inserting a conversion */
1224:
1225: if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
1226: if( t == p->in.type ){
1227: p->fn.cdim = d;
1228: p->fn.csiz = s;
1229: return( p );
1230: }
1231:
1232: if( t & TMASK ){
1233: /* non-simple type */
1234: return( block( PCONV, p, NIL, t, d, s ) );
1235: }
1236:
1237: if( p->in.op == ICON ){
1238: if (t == DOUBLE) {
1239: p->in.op = DCON;
1240: if (ISUNSIGNED(p->in.type))
1241: p->dpn.dval = (U_CONSZ) p->tn.lval;
1242: else
1243: p->dpn.dval = p->tn.lval;
1244: p->in.type = p->fn.csiz = t;
1245: return (clocal(p));
1246: }
1247: if (t == FLOAT) {
1248: p->in.op = FCON;
1249: if( ISUNSIGNED(p->in.type) ){
1250: p->fpn.fval = (U_CONSZ) p->tn.lval;
1251: }
1252: else {
1253: p->fpn.fval = p->tn.lval;
1254: }
1255:
1256: p->in.type = p->fn.csiz = t;
1257: return( clocal(p) );
1258: }
1259: }
1260: else if (p->in.op == FCON && t == DOUBLE) {
1261: double db;
1262:
1263: p->in.op = DCON;
1264: db = p->fpn.fval;
1265: p->dpn.dval = db;
1266: p->in.type = p->fn.csiz = t;
1267: return (clocal(p));
1268: } else if (p->in.op == DCON && t == FLOAT) {
1269: float fl;
1270:
1271: p->in.op = FCON;
1272: fl = p->dpn.dval;
1273: #ifdef notdef
1274: if (fl != p->dpn.dval)
1275: werror("float conversion loses precision");
1276: #endif
1277: p->fpn.fval = fl;
1278: p->in.type = p->fn.csiz = t;
1279: return (clocal(p));
1280: }
1281:
1282: return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
1283:
1284: }
1285:
1286: NODE *
1287: block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
1288:
1289: register NODE *p;
1290:
1291: p = talloc();
1292: p->in.op = o;
1293: p->in.left = l;
1294: p->in.right = r;
1295: p->in.type = t;
1296: p->fn.cdim = d;
1297: p->fn.csiz = s;
1298: return(p);
1299: }
1300:
1301: icons(p) register NODE *p; {
1302: /* if p is an integer constant, return its value */
1303: int val;
1304:
1305: if( p->in.op != ICON ){
1306: uerror( "constant expected");
1307: val = 1;
1308: }
1309: else {
1310: val = p->tn.lval;
1311: if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
1312: }
1313: tfree( p );
1314: return(val);
1315: }
1316:
1317: /* the intent of this table is to examine the
1318: operators, and to check them for
1319: correctness.
1320:
1321: The table is searched for the op and the
1322: modified type (where this is one of the
1323: types INT (includes char and short), LONG,
1324: DOUBLE (includes FLOAT), and POINTER
1325:
1326: The default action is to make the node type integer
1327:
1328: The actions taken include:
1329: PUN check for puns
1330: CVTL convert the left operand
1331: CVTR convert the right operand
1332: TYPL the type is determined by the left operand
1333: TYPR the type is determined by the right operand
1334: TYMATCH force type of left and right to match, by inserting conversions
1335: PTMATCH like TYMATCH, but for pointers
1336: LVAL left operand must be lval
1337: CVTO convert the op
1338: NCVT do not convert the operands
1339: OTHER handled by code
1340: NCVTR convert the left operand, not the right...
1341:
1342: */
1343:
1344: # define MINT 01 /* integer */
1345: # define MDBI 02 /* integer or double */
1346: # define MSTR 04 /* structure */
1347: # define MPTR 010 /* pointer */
1348: # define MPTI 020 /* pointer or integer */
1349: # define MENU 040 /* enumeration variable or member */
1350: # define MVOID 0100000 /* void type */
1351:
1352: opact( p ) NODE *p; {
1353:
1354: register mt12, mt1, mt2, o;
1355:
1356: mt1 = mt2 = mt12 = 0;
1357:
1358: switch( optype(o=p->in.op) ){
1359:
1360: case BITYPE:
1361: mt2 = moditype( p->in.right->in.type );
1362: case UTYPE:
1363: mt1 = moditype( p->in.left->in.type );
1364: break;
1365:
1366: }
1367:
1368: if( ((mt1 | mt2) & MVOID) &&
1369: o != COMOP &&
1370: o != COLON &&
1371: !(o == QUEST && (mt1 & MVOID) == 0) &&
1372: !(o == CAST && (mt1 & MVOID)) ){
1373: /* if lhs of RETURN is void, grammar will complain */
1374: if( o != RETURN )
1375: uerror( "value of void expression used" );
1376: return( NCVT );
1377: }
1378: mt12 = mt1 & mt2;
1379:
1380: switch( o ){
1381:
1382: case NAME :
1383: case STRING :
1384: case ICON :
1385: case FCON :
1386: case DCON :
1387: case CALL :
1388: case UNARY CALL:
1389: case UNARY MUL:
1390: { return( OTHER ); }
1391: case UNARY MINUS:
1392: if( mt1 & MENU ) return( 0 );
1393: if( mt1 & MDBI ) return( TYPL );
1394: break;
1395:
1396: case COMPL:
1397: if( mt1 & MENU ) return( 0 );
1398: if( mt1 & MINT ) return( TYPL );
1399: break;
1400:
1401: case UNARY AND:
1402: return( NCVT+OTHER );
1403: case INIT:
1404: case CM:
1405: return( 0 );
1406:
1407: case NOT:
1408: case CBRANCH:
1409: if( mt1 & MSTR ) break;
1410: return( 0 );
1411:
1412: case ANDAND:
1413: case OROR:
1414: if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
1415: return( 0 );
1416:
1417: case MUL:
1418: case DIV:
1419: if( mt12 & MDBI ) return( TYMATCH );
1420: break;
1421:
1422: case MOD:
1423: case AND:
1424: case OR:
1425: case ER:
1426: if( mt12 & MINT ) return( TYMATCH );
1427: break;
1428:
1429: case LS:
1430: case RS:
1431: if( mt12 & MINT ) return( OTHER );
1432: break;
1433:
1434: case EQ:
1435: case NE:
1436: case LT:
1437: case LE:
1438: case GT:
1439: case GE:
1440: if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
1441: if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
1442: else if( mt12 & MPTR ) return( PTMATCH+PUN );
1443: else if( mt12 & MPTI ) return( PTMATCH+PUN );
1444: else break;
1445:
1446: case QUEST:
1447: case COMOP:
1448: if( mt2&MENU ) return( TYPR+NCVTR );
1449: return( TYPR );
1450:
1451: case STREF:
1452: return( NCVTR+OTHER );
1453:
1454: case FORCE:
1455: return( TYPL );
1456:
1457: case COLON:
1458: if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
1459: else if( mt12 & MDBI ) return( NCVT+TYMATCH );
1460: else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1461: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1462: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1463: else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1464: else if( mt12 == MVOID ) return( NCVT+TYPL );
1465: break;
1466:
1467: case ASSIGN:
1468: case RETURN:
1469: if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1470: else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
1471: case CAST:
1472: if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
1473: else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
1474: else if( mt2 == MVOID &&
1475: ( p->in.right->in.op == CALL ||
1476: p->in.right->in.op == UNARY CALL)) break;
1477: else if( (mt1 & MPTR) && (mt2 & MPTI) )
1478: return( LVAL+PTMATCH+PUN );
1479: else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1480: break;
1481:
1482: case ASG LS:
1483: case ASG RS:
1484: if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1485: break;
1486:
1487: case ASG MUL:
1488: case ASG DIV:
1489: if( mt12 & MDBI ) return( LVAL+TYMATCH );
1490: break;
1491:
1492: case ASG MOD:
1493: case ASG AND:
1494: case ASG OR:
1495: case ASG ER:
1496: if( mt12 & MINT ) return( LVAL+TYMATCH );
1497: break;
1498:
1499: case ASG PLUS:
1500: case ASG MINUS:
1501: case INCR:
1502: case DECR:
1503: if( mt12 & MDBI ) return( TYMATCH+LVAL );
1504: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1505: break;
1506:
1507: case MINUS:
1508: if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1509: if( mt2 & MPTR ) break;
1510: case PLUS:
1511: if( mt12 & MDBI ) return( TYMATCH );
1512: else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1513: else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1514:
1515: }
1516: if( mt12 == MSTR )
1517: uerror( "%s is not a permitted struct/union operation", opst[o] );
1518: else
1519: uerror( "operands of %s have incompatible types", opst[o] );
1520: return( NCVT );
1521: }
1522:
1523: moditype( ty ) TWORD ty; {
1524:
1525: switch( ty ){
1526:
1527: case UNDEF:
1528: return( MVOID );
1529: case ENUMTY:
1530: case MOETY:
1531: return( MENU|MINT|MDBI|MPTI ); /* enums are ints */
1532:
1533: case STRTY:
1534: case UNIONTY:
1535: return( MSTR );
1536:
1537: case CHAR:
1538: case SHORT:
1539: case UCHAR:
1540: case USHORT:
1541: return( MINT|MPTI|MDBI );
1542: case UNSIGNED:
1543: case ULONG:
1544: case INT:
1545: case LONG:
1546: return( MINT|MDBI|MPTI );
1547: case FLOAT:
1548: case DOUBLE:
1549: return( MDBI );
1550: default:
1551: return( MPTR|MPTI );
1552:
1553: }
1554: }
1555:
1556: NODE *
1557: doszof( p ) register NODE *p; {
1558: /* do sizeof p */
1559: int i;
1560:
1561: /* whatever is the meaning of this if it is a bitfield? */
1562: i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1563:
1564: tfree(p);
1565: if( i <= 0 ) werror( "sizeof returns 0" );
1566: return( bcon( i ) );
1567: }
1568:
1569: # ifndef BUG2
1570: eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1571: register ty;
1572:
1573: *a = *b = down+1;
1574: while( down > 1 ){
1575: printf( "\t" );
1576: down -= 2;
1577: }
1578: if( down ) printf( " " );
1579:
1580: ty = optype( p->in.op );
1581:
1582: printf("%o) %s, ", p, opst[p->in.op] );
1583: if( ty == LTYPE ){
1584: printf( CONFMT, p->tn.lval );
1585: printf( ", %d, ", p->tn.rval );
1586: }
1587: tprint( p->in.type );
1588: printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1589: }
1590: # endif
1591:
1592: #ifndef PRTDCON
1593: prtdcon( p ) register NODE *p; {
1594: int o = p->in.op, i;
1595:
1596: if( o == DCON || o == FCON ){
1597: (void) locctr( DATA );
1598: defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1599: deflab( i = getlab() );
1600: if( o == FCON )
1601: fincode( p->fpn.fval, SZFLOAT );
1602: else
1603: fincode( p->dpn.dval, SZDOUBLE );
1604: p->tn.lval = 0;
1605: p->tn.rval = -i;
1606: p->in.type = (o == DCON ? DOUBLE : FLOAT);
1607: p->in.op = NAME;
1608: }
1609: }
1610: #endif PRTDCON
1611:
1612:
1613: int edebug = 0;
1614: ecomp( p ) register NODE *p; {
1615: # ifndef BUG2
1616: if( edebug ) fwalk( p, eprint, 0 );
1617: # endif
1618: if( !reached ){
1619: werror( "statement not reached" );
1620: reached = 1;
1621: }
1622: p = optim(p);
1623: walkf( p, prtdcon );
1624: (void) locctr( PROG );
1625: ecode( p );
1626: tfree(p);
1627: }
1628:
1629: # ifdef STDPRTREE
1630: # ifndef ONEPASS
1631:
1632: prtree(p) register NODE *p; {
1633:
1634: register struct symtab *q;
1635: register ty;
1636:
1637: # ifdef MYPRTREE
1638: MYPRTREE(p); /* local action can be taken here; then return... */
1639: #endif
1640:
1641: ty = optype(p->in.op);
1642:
1643: printf( "%d\t", p->in.op );
1644:
1645: if( ty == LTYPE ) {
1646: printf( CONFMT, p->tn.lval );
1647: printf( "\t" );
1648: }
1649: if( ty != BITYPE ) {
1650: if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1651: else printf( "%d\t", p->tn.rval );
1652: }
1653:
1654: printf( "%o\t", p->in.type );
1655:
1656: /* handle special cases */
1657:
1658: switch( p->in.op ){
1659:
1660: case NAME:
1661: case ICON:
1662: /* print external name */
1663: if( p->tn.rval == NONAME ) printf( "\n" );
1664: else if( p->tn.rval >= 0 ){
1665: q = &stab[p->tn.rval];
1666: printf( "%s\n", exname(q->sname) );
1667: }
1668: else { /* label */
1669: printf( LABFMT, -p->tn.rval );
1670: }
1671: break;
1672:
1673: case STARG:
1674: case STASG:
1675: case STCALL:
1676: case UNARY STCALL:
1677: /* print out size */
1678: /* use lhs size, in order to avoid hassles with the structure `.' operator */
1679:
1680: /* note: p->in.left not a field... */
1681: printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1682: printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1683: break;
1684:
1685: default:
1686: printf( "\n" );
1687: }
1688:
1689: if( ty != LTYPE ) prtree( p->in.left );
1690: if( ty == BITYPE ) prtree( p->in.right );
1691:
1692: }
1693:
1694: # else
1695:
1696: p2tree(p) register NODE *p; {
1697: register ty;
1698:
1699: # ifdef MYP2TREE
1700: MYP2TREE(p); /* local action can be taken here; then return... */
1701: # endif
1702:
1703: ty = optype(p->in.op);
1704:
1705: switch( p->in.op ){
1706:
1707: case NAME:
1708: case ICON:
1709: #ifndef FLEXNAMES
1710: if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1711: #else
1712: if( p->tn.rval == NONAME ) p->in.name = "";
1713: #endif
1714: else if( p->tn.rval >= 0 ){ /* copy name from exname */
1715: register char *cp;
1716: cp = exname( stab[p->tn.rval].sname );
1717: #ifndef FLEXNAMES
1718: {
1719: register i;
1720: for( i=0; i<NCHNAM; ++i )
1721: p->in.name[i] = *cp++;
1722: }
1723: #else
1724: p->in.name = tstr(cp);
1725: #endif
1726: }
1727: #ifndef FLEXNAMES
1728: else sprintf( p->in.name, LABFMT, -p->tn.rval );
1729: #else
1730: else {
1731: char temp[32];
1732: sprintf( temp, LABFMT, -p->tn.rval );
1733: p->in.name = tstr(temp);
1734: }
1735: #endif
1736: break;
1737:
1738: case STARG:
1739: case STASG:
1740: case STCALL:
1741: case UNARY STCALL:
1742: /* set up size parameters */
1743: p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1744: p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1745: break;
1746:
1747: case REG:
1748: rbusy( p->tn.rval, p->in.type );
1749: default:
1750: #ifndef FLEXNAMES
1751: p->in.name[0] = '\0';
1752: #else
1753: p->in.name = "";
1754: #endif
1755: }
1756:
1757: p->in.rall = NOPREF;
1758:
1759: if( ty != LTYPE ) p2tree( p->in.left );
1760: if( ty == BITYPE ) p2tree( p->in.right );
1761: }
1762:
1763: # endif
1764: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.