1 #ifndef lint
2 static char *sccsid ="@(#)trees.c 4.37 (Berkeley) 06/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
printact(t,acts)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 *
buildtree(o,l,r)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
fpe()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 *
fixargs(p)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
chkstr(i,j,type)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
conval(p,o,q)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
chkpun(p)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 *
stref(p)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
notlval(p)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 *
bcon(i)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 *
bpsize(p)958 bpsize(p) register NODE *p; {
959 return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
960 }
961
962 OFFSZ
psize(p)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 *
convert(p,f)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
econvert(p)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 *
pconvert(p)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 *
oconvert(p)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 *
ptmatch(p)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 *
tymatch(p)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 *
makety(p,t,d,s)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 *
block(o,l,r,t,d,s)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
icons(p)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
opact(p)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
moditype(ty)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 *
doszof(p)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
eprint(p,down,a,b)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
prtdcon(p)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;
ecomp(p)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
prtree(p)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
p2tree(p)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
1765