BSD 3 development
[unix-history] / usr / src / cmd / mip / trees.c
CommitLineData
79730fb7
BJ
1# include "mfile1"
2
3/* some special actions, used in finding the type of nodes */
4# define NCVT 01
5# define PUN 02
6# define TYPL 04
7# define TYPR 010
8# define TYMATCH 040
9# define LVAL 0100
10# define CVTO 0200
11# define CVTL 0400
12# define CVTR 01000
13# define PTMATCH 02000
14# define OTHER 04000
15# define NCVTR 010000
16
17/* node conventions:
18
19 NAME: rval>0 is stab index for external
20 rval<0 is -inlabel number
21 lval is offset in bits
22 ICON: lval has the value
23 rval has the STAB index, or - label number,
24 if a name whose address is in the constant
25 rval = NONAME means no name
26 REG: rval is reg. identification cookie
27
28 */
29
30int bdebug = 0;
31
32NODE *
33buildtree( o, l, r ) register NODE *l, *r; {
34 register NODE *p, *q;
35 register actions;
36 register opty;
37 register struct symtab *sp;
38 register NODE *lr, *ll;
39 int i;
40 extern int eprint();
41
42 if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
43 opty = optype(o);
44
45 /* check for constants */
46
47 if( opty == UTYPE && l->op == ICON ){
48
49 switch( o ){
50
51 case NOT:
52 if( hflag ) werror( "constant argument to NOT" );
53 case UNARY MINUS:
54 case COMPL:
55 if( conval( l, o, l ) ) return(l);
56 break;
57
58 }
59 }
60
61 else if( o==UNARY MINUS && l->op==FCON ){
62 l->dval = -l->dval;
63 return(l);
64 }
65
66 else if( o==QUEST && l->op==ICON ) {
67 l->op = FREE;
68 r->op = FREE;
69 if( l->lval ){
70 tfree( r->right );
71 return( r->left );
72 }
73 else {
74 tfree( r->left );
75 return( r->right );
76 }
77 }
78
79 else if( (o==ANDAND || o==OROR) && (l->op==ICON||r->op==ICON) ) goto ccwarn;
80
81 else if( opty == BITYPE && l->op == ICON && r->op == ICON ){
82
83 switch( o ){
84
85 case ULT:
86 case UGT:
87 case ULE:
88 case UGE:
89 case LT:
90 case GT:
91 case LE:
92 case GE:
93 case EQ:
94 case NE:
95 case ANDAND:
96 case OROR:
97 case CBRANCH:
98
99 ccwarn:
100 if( hflag ) werror( "constant in conditional context" );
101
102 case PLUS:
103 case MINUS:
104 case MUL:
105 case DIV:
106 case MOD:
107 case AND:
108 case OR:
109 case ER:
110 case LS:
111 case RS:
112 if( conval( l, o, r ) ) {
113 r->op = FREE;
114 return(l);
115 }
116 break;
117 }
118 }
119
120 else if( opty == BITYPE && (l->op==FCON||l->op==ICON) &&
121 (r->op==FCON||r->op==ICON) ){
122 switch(o){
123 case PLUS:
124 case MINUS:
125 case MUL:
126 case DIV:
127 if( l->op == ICON ){
128 l->dval = l->lval;
129 }
130 if( r->op == ICON ){
131 r->dval = r->lval;
132 }
133 l->op = FCON;
134 l->type = l->csiz = DOUBLE;
135 r->op = FREE;
136 switch(o){
137 case PLUS:
138 l->dval += r->dval;
139 return(l);
140 case MINUS:
141 l->dval -= r->dval;
142 return(l);
143 case MUL:
144 l->dval *= r->dval;
145 return(l);
146 case DIV:
147 if( r->dval == 0 ) uerror( "division by 0." );
148 else l->dval /= r->dval;
149 return(l);
150 }
151 }
152 }
153
154 /* its real; we must make a new node */
155
156 p = block( o, l, r, INT, 0, INT );
157
158 actions = opact(p);
159
160 if( actions&LVAL ){ /* check left descendent */
161 if( notlval(p->left) ) {
162 uerror( "lvalue required" );
163 }
164 }
165
166 if( actions & NCVTR ){
167 p->left = pconvert( p->left );
168 }
169 else if( !(actions & NCVT ) ){
170 switch( opty ){
171
172 case BITYPE:
173 p->right = pconvert( p->right );
174 case UTYPE:
175 p->left = pconvert( p->left );
176
177 }
178 }
179
180 if( (actions&PUN) && (o!=CAST||cflag) ){
181 chkpun(p);
182 }
183
184 if( actions & (TYPL|TYPR) ){
185
186 q = (actions&TYPL) ? p->left : p->right;
187
188 p->type = q->type;
189 p->cdim = q->cdim;
190 p->csiz = q->csiz;
191 }
192
193 if( actions & CVTL ) p = convert( p, CVTL );
194 if( actions & CVTR ) p = convert( p, CVTR );
195 if( actions & TYMATCH ) p = tymatch(p);
196 if( actions & PTMATCH ) p = ptmatch(p);
197
198 if( actions & OTHER ){
199 l = p->left;
200 r = p->right;
201
202 switch(o){
203
204 case NAME:
205 sp = &stab[idname];
206 if( sp->stype == UNDEF ){
207 uerror( "%.8s undefined", sp->sname );
208 /* make p look reasonable */
209 p->type = p->cdim = p->csiz = INT;
210 p->rval = idname;
211 p->lval = 0;
212 defid( p, SNULL );
213 break;
214 }
215 p->type = sp->stype;
216 p->cdim = sp->dimoff;
217 p->csiz = sp->sizoff;
218 p->lval = 0;
219 p->rval = idname;
220 /* special case: MOETY is really an ICON... */
221 if( p->type == MOETY ){
222 p->rval = NONAME;
223 p->lval = sp->offset;
224 p->cdim = 0;
225 p->type = ENUMTY;
226 p->op = ICON;
227 }
228 break;
229
230 case ICON:
231 p->type = INT;
232 p->cdim = 0;
233 p->csiz = INT;
234 break;
235
236 case STRING:
237 p->op = NAME;
238 p->type = CHAR+ARY;
239 p->lval = 0;
240 p->rval = NOLAB;
241 p->cdim = curdim;
242 p->csiz = CHAR;
243 break;
244
245 case FCON:
246 p->lval = 0;
247 p->rval = 0;
248 p->type = DOUBLE;
249 p->cdim = 0;
250 p->csiz = DOUBLE;
251 break;
252
253 case STREF:
254 /* p->x turned into *(p+offset) */
255 /* rhs must be a name; check correctness */
256
257 i = r->rval;
258 if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
259 uerror( "member of structure or union required" );
260 }
261 else {
262 register j;
263 if( l->type != PTR+STRTY && l->type != PTR+UNIONTY ){
264 werror( "struct/union or struct/union pointer required" );
265 }
266 else if( (j=l->csiz+1)<0 ) cerror( "undefined structure or union" );
267 else if( !chkstr( i, dimtab[j], DECREF(l->type) ) ){
268 werror( "illegal member use: %.8s", stab[i].sname );
269 }
270 }
271
272 p = stref( p );
273 break;
274
275 case UNARY MUL:
276 if( l->op == UNARY AND ){
277 p->op = l->op = FREE;
278 p = l->left;
279 }
280 if( !ISPTR(l->type))uerror("illegal indirection");
281 p->type = DECREF(l->type);
282 p->cdim = l->cdim;
283 p->csiz = l->csiz;
284 break;
285
286 case UNARY AND:
287 switch( l->op ){
288
289 case UNARY MUL:
290 p->op = l->op = FREE;
291 p = l->left;
292 case NAME:
293 p->type = INCREF( l->type );
294 p->cdim = l->cdim;
295 p->csiz = l->csiz;
296 break;
297
298 case COMOP:
299 lr = buildtree( UNARY AND, l->right, NIL );
300 p->op = l->op = FREE;
301 p = buildtree( COMOP, l->left, lr );
302 break;
303
304 case QUEST:
305 lr = buildtree( UNARY AND, l->right->right, NIL );
306 ll = buildtree( UNARY AND, l->right->left, NIL );
307 p->op = l->op = l->right->op = FREE;
308 p = buildtree( QUEST, l->left, buildtree( COLON, ll, lr ) );
309 break;
310
311 default:
312 uerror( "unacceptable operand of &" );
313 break;
314 }
315 break;
316
317 case LS:
318 case RS:
319 case ASG LS:
320 case ASG RS:
321 if(tsize(p->right->type, p->right->cdim, p->right->csiz) > SZINT)
322 p->right = makety(p->right, INT, 0, INT );
323 break;
324
325 case RETURN:
326 case ASSIGN:
327 case CAST:
328 /* structure assignment */
329 /* take the addresses of the two sides; then make an
330 /* operator using STASG and
331 /* the addresses of left and right */
332
333 {
334 register TWORD t;
335 register d, s;
336
337 if( l->csiz != r->csiz ) uerror( "assignment of different structures" );
338
339 r = buildtree( UNARY AND, r, NIL );
340 t = r->type;
341 d = r->cdim;
342 s = r->csiz;
343
344 l = block( STASG, l, r, t, d, s );
345
346 if( o == RETURN ){
347 p->op = FREE;
348 p = l;
349 break;
350 }
351
352 p->op = UNARY MUL;
353 p->left = l;
354 p->right = NIL;
355 break;
356 }
357 case COLON:
358 /* structure colon */
359
360 if( l->csiz != r->csiz ) uerror( "type clash in conditional" );
361 break;
362
363 case CALL:
364 p->right = r = strargs( p->right );
365 case UNARY CALL:
366 if( !ISPTR(l->type)) uerror("illegal function");
367 p->type = DECREF(l->type);
368 if( !ISFTN(p->type)) uerror("illegal function");
369 p->type = DECREF( p->type );
370 p->cdim = l->cdim;
371 p->csiz = l->csiz;
372 if( l->op == UNARY AND && l->left->op == NAME &&
373 l->left->rval >= 0 && l->left->rval != NONAME &&
374 ( (i=stab[l->left->rval].sclass) == FORTRAN || i==UFORTRAN ) ){
375 p->op += (FORTCALL-CALL);
376 }
377 if( p->type == STRTY || p->type == UNIONTY ){
378 /* function returning structure */
379 /* make function really return ptr to str., with * */
380
381 p->op += STCALL-CALL;
382 p->type = INCREF( p->type );
383 p = buildtree( UNARY MUL, p, NIL );
384
385 }
386 break;
387
388 default:
389 cerror( "other code %d", o );
390 }
391
392 }
393
394 if( actions & CVTO ) p = oconvert(p);
395 p = clocal(p);
396
397 if( bdebug ) fwalk( p, eprint, 0 );
398
399 return(p);
400
401 }
402
403NODE *
404strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */
405
406 if( p->op == CM ){
407 p->left = strargs( p->left );
408 p->right = strargs( p->right );
409 return( p );
410 }
411
412 if( p->type == STRTY || p->type == UNIONTY ){
413 p = block( STARG, p, NIL, p->type, p->cdim, p->csiz );
414 p->left = buildtree( UNARY AND, p->left, NIL );
415 p = clocal(p);
416 }
417 return( p );
418 }
419
420chkstr( i, j, type ) TWORD type; {
421 /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
422 /* i has been checked to contain a MOS or MOU */
423 /* j is the index in dimtab of the members... */
424 int k, kk;
425
426 extern int ddebug;
427
428 if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
429 if( (k = j) < 0 ) uerror( "undefined structure or union" );
430 else {
431 for( ; (kk = dimtab[k] ) >= 0; ++k ){
432 if( kk >= SYMTSZ ){
433 cerror( "gummy structure" );
434 return(1);
435 }
436 if( kk == i ) return( 1 );
437 switch( stab[kk].stype ){
438
439 case STRTY:
440 case UNIONTY:
441 if( type == STRTY ) continue; /* no recursive looking for strs */
442 if( chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ) return(1);
443 }
444 }
445 }
446 return( 0 );
447 }
448
449conval( p, o, q ) register NODE *p, *q; {
450 /* apply the op o to the lval part of p; if binary, rhs is val */
451 int i, u;
452 CONSZ val;
453
454 val = q->lval;
455 u = ISUNSIGNED(p->type) || ISUNSIGNED(q->type);
456 if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
457
458 if( p->rval != NONAME && q->rval != NONAME ) return(0);
459 if( q->rval != NONAME && o!=PLUS ) return(0);
460 if( p->rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
461
462 switch( o ){
463
464 case PLUS:
465 p->lval += val;
466 if( p->rval == NONAME ){
467 p->rval = q->rval;
468 p->type = q->type;
469 }
470 break;
471 case MINUS:
472 p->lval -= val;
473 break;
474 case MUL:
475 p->lval *= val;
476 break;
477 case DIV:
478 if( val == 0 ) uerror( "division by 0" );
479 else p->lval /= val;
480 break;
481 case MOD:
482 if( val == 0 ) uerror( "division by 0" );
483 else p->lval %= val;
484 break;
485 case AND:
486 p->lval &= val;
487 break;
488 case OR:
489 p->lval |= val;
490 break;
491 case ER:
492 p->lval ^= val;
493 break;
494 case LS:
495 i = val;
496 p->lval = p->lval << i;
497 break;
498 case RS:
499 i = val;
500 p->lval = p->lval >> i;
501 break;
502
503 case UNARY MINUS:
504 p->lval = - p->lval;
505 break;
506 case COMPL:
507 p->lval = ~p->lval;
508 break;
509 case NOT:
510 p->lval = !p->lval;
511 break;
512 case LT:
513 p->lval = p->lval < val;
514 break;
515 case LE:
516 p->lval = p->lval <= val;
517 break;
518 case GT:
519 p->lval = p->lval > val;
520 break;
521 case GE:
522 p->lval = p->lval >= val;
523 break;
524 case ULT:
525 p->lval = (p->lval-val)<0;
526 break;
527 case ULE:
528 p->lval = (p->lval-val)<=0;
529 break;
530 case UGE:
531 p->lval = (p->lval-val)>=0;
532 break;
533 case UGT:
534 p->lval = (p->lval-val)>0;
535 break;
536 case EQ:
537 p->lval = p->lval == val;
538 break;
539 case NE:
540 p->lval = p->lval != val;
541 break;
542 default:
543 return(0);
544 }
545 return(1);
546 }
547
548chkpun(p) register NODE *p; {
549
550 /* checks p for the existance of a pun */
551
552 /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
553
554 /* one case is when enumerations are used: this applies only to lint */
555 /* in the other case, one operand is a pointer, the other integer type */
556 /* we check that this integer is in fact a constant zero... */
557
558 /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
559 /* this falls out, because the LHS is never 0 */
560
561 register NODE *q;
562 register t1, t2;
563 register d1, d2;
564
565 t1 = p->left->type;
566 t2 = p->right->type;
567
568 if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
569 if( logop( p->op ) && p->op != EQ && p->op != NE ) {
570 uerror( "illegal comparison of enums" );
571 return;
572 }
573 if( t1==ENUMTY && t2==ENUMTY && p->left->csiz==p->right->csiz ) return;
574 werror( "enumeration type clash, operator %s", opst[p->op] );
575 return;
576 }
577
578 if( ISPTR(t1) || ISARY(t1) ) q = p->right;
579 else q = p->left;
580
581 if( !ISPTR(q->type) && !ISARY(q->type) ){
582 if( q->op != ICON || q->lval != 0 ){
583 werror( "illegal combination of pointer and integer");
584 }
585 }
586 else {
587 d1 = p->left->cdim;
588 d2 = p->right->cdim;
589 for( ;; ){
590 if( t1 == t2 ) {;
591 if( p->left->csiz != p->right->csiz ) {
592 werror( "illegal structure pointer combination" );
593 }
594 return;
595 }
596 if( ISARY(t1) || ISPTR(t1) ){
597 if( !ISARY(t2) && !ISPTR(t2) ) break;
598 if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
599 werror( "illegal array size combination" );
600 return;
601 }
602 if( ISARY(t1) ) ++d1;
603 if( ISARY(t2) ) ++d2;
604 }
605 else break;
606 t1 = DECREF(t1);
607 t2 = DECREF(t2);
608 }
609 werror( "illegal pointer combination" );
610 }
611
612 }
613
614NODE *
615stref( p ) register NODE *p; {
616
617 TWORD t;
618 int d, s, dsc;
619 OFFSZ off;
620 register struct symtab *q;
621
622 /* make p->x */
623 /* this is also used to reference automatic variables */
624
625 q = &stab[p->right->rval];
626 p->right->op = FREE;
627 p->op = FREE;
628 p = pconvert( p->left );
629
630 /* make p look like ptr to x */
631
632 if( !ISPTR(p->type)){
633 p->type = PTR+UNIONTY;
634 }
635
636 t = INCREF( q->stype );
637 d = q->dimoff;
638 s = q->sizoff;
639
640 p = makety( p, t, d, s );
641
642 /* compute the offset to be added */
643
644 off = q->offset;
645 dsc = q->sclass;
646
647 if( dsc & FIELD ){ /* make fields look like ints */
648 off = (off/ALINT)*ALINT;
649 s = INT;
650 }
651 if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
652
653 p = buildtree( UNARY MUL, p, NIL );
654
655 /* if field, build field info */
656
657 if( dsc & FIELD ){
658 p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
659 p->rval = PKFIELD( dsc&FLDSIZ, q->offset%ALINT );
660 }
661
662 return( clocal(p) );
663 }
664
665notlval(p) register NODE *p; {
666
667 /* return 0 if p an lvalue, 1 otherwise */
668
669 again:
670
671 switch( p->op ){
672
673 case FLD:
674 p = p->left;
675 goto again;
676
677 case NAME:
678 case OREG:
679 case UNARY MUL:
680 if( ISARY(p->type) || ISFTN(p->type) ) return(1);
681 case REG:
682 return(0);
683
684 default:
685 return(1);
686
687 }
688
689 }
690
691NODE *
692bcon( i ){ /* make a constant node with value i */
693 register NODE *p;
694
695 p = block( ICON, NIL, NIL, INT, 0, INT );
696 p->lval = i;
697 p->rval = NONAME;
698 return( clocal(p) );
699 }
700
701NODE *
702bpsize(p) register NODE *p; {
703 return( offcon( psize(p), p->type, p->cdim, p->csiz ) );
704 }
705
706OFFSZ
707psize( p ) NODE *p; {
708 /* p is a node of type pointer; psize returns the
709 size of the thing pointed to */
710
711 if( !ISPTR(p->type) ){
712 uerror( "pointer required");
713 return( SZINT );
714 }
715 /* note: no pointers to fields */
716 return( tsize( DECREF(p->type), p->cdim, p->csiz ) );
717 }
718
719NODE *
720convert( p, f ) register NODE *p; {
721 /* convert an operand of p
722 f is either CVTL or CVTR
723 operand has type int, and is converted by the size of the other side
724 */
725
726 register NODE *q, *r;
727
728 q = (f==CVTL)?p->left:p->right;
729
730 r = block( PMCONV,
731 q, bpsize(f==CVTL?p->right:p->left), INT, 0, INT );
732 r = clocal(r);
733 if( f == CVTL )
734 p->left = r;
735 else
736 p->right = r;
737 return(p);
738
739 }
740
741econvert( p ) register NODE *p; {
742
743 /* change enums to ints, or appropriate types */
744
745 register TWORD ty;
746
747 if( (ty=BTYPE(p->type)) == ENUMTY || ty == MOETY ) {
748 if( dimtab[ p->csiz ] == SZCHAR ) ty = CHAR;
749 else if( dimtab[ p->csiz ] == SZINT ) ty = INT;
750 else if( dimtab[ p->csiz ] == SZSHORT ) ty = SHORT;
751 else ty = LONG;
752 ty = ctype( ty );
753 p->csiz = ty;
754 MODTYPE(p->type,ty);
755 if( p->op == ICON && ty != LONG ) p->type = p->csiz = INT;
756 }
757 }
758
759NODE *
760pconvert( p ) register NODE *p; {
761
762 /* if p should be changed into a pointer, do so */
763
764 if( ISARY( p->type) ){
765 p->type = DECREF( p->type );
766 ++p->cdim;
767 return( buildtree( UNARY AND, p, NIL ) );
768 }
769 if( ISFTN( p->type) )
770 return( buildtree( UNARY AND, p, NIL ) );
771
772 return( p );
773 }
774
775NODE *
776oconvert(p) register NODE *p; {
777 /* convert the result itself: used for pointer and unsigned */
778
779 switch(p->op) {
780
781 case LE:
782 case LT:
783 case GE:
784 case GT:
785 if( ISUNSIGNED(p->left->type) || ISUNSIGNED(p->right->type) ) p->op += (ULE-LE);
786 case EQ:
787 case NE:
788 return( p );
789
790 case MINUS:
791 return( clocal( block( PVCONV,
792 p, bpsize(p->left), INT, 0, INT ) ) );
793 }
794
795 cerror( "illegal oconvert: %d", p->op );
796
797 return(p);
798 }
799
800NODE *
801ptmatch(p) register NODE *p; {
802
803 /* makes the operands of p agree; they are
804 either pointers or integers, by this time */
805 /* with MINUS, the sizes must be the same */
806 /* with COLON, the types must be the same */
807
808 TWORD t1, t2, t;
809 int o, d2, d, s2, s;
810
811 o = p->op;
812 t = t1 = p->left->type;
813 t2 = p->right->type;
814 d = p->left->cdim;
815 d2 = p->right->cdim;
816 s = p->left->csiz;
817 s2 = p->right->csiz;
818
819 switch( o ){
820
821 case ASSIGN:
822 case RETURN:
823 case CAST:
824 { break; }
825
826 case MINUS:
827 { if( psize(p->left) != psize(p->right) ){
828 uerror( "illegal pointer subtraction");
829 }
830 break;
831 }
832 case COLON:
833 { if( t1 != t2 ) uerror( "illegal types in :");
834 break;
835 }
836 default: /* must work harder: relationals or comparisons */
837
838 if( !ISPTR(t1) ){
839 t = t2;
840 d = d2;
841 s = s2;
842 break;
843 }
844 if( !ISPTR(t2) ){
845 break;
846 }
847
848 /* both are pointers */
849 if( talign(t2,s2) < talign(t,s) ){
850 t = t2;
851 s = s2;
852 }
853 break;
854 }
855
856 p->left = makety( p->left, t, d, s );
857 p->right = makety( p->right, t, d, s );
858 if( o!=MINUS && !logop(o) ){
859
860 p->type = t;
861 p->cdim = d;
862 p->csiz = s;
863 }
864
865 return(clocal(p));
866 }
867
868int tdebug = 0;
869
870NODE *
871tymatch(p) register NODE *p; {
872
873 /* satisfy the types of various arithmetic binary ops */
874
875 /* rules are:
876 if assignment, op, type of LHS
877 if any float or doubles, make double
878 if any longs, make long
879 otherwise, make int
880 if either operand is unsigned, the result is...
881 */
882
883 register TWORD t1, t2, t, tu;
884 register o, u;
885
886 o = p->op;
887
888 t1 = p->left->type;
889 t2 = p->right->type;
890
891 u = 0;
892 if( ISUNSIGNED(t1) ){
893 u = 1;
894 t1 = DEUNSIGN(t1);
895 }
896 if( ISUNSIGNED(t2) ){
897 u = 1;
898 t2 = DEUNSIGN(t2);
899 }
900
901 if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
902 if( t2 == CHAR || t2 == SHORT ) t2 = INT;
903
904 if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE;
905 else if( t1==LONG || t2==LONG ) t = LONG;
906 else t = INT;
907
908 if( asgop(o) ){
909 tu = p->left->type;
910 t = t1;
911 }
912 else {
913 tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
914 }
915
916 /* because expressions have values that are at least as wide
917 as INT or UNSIGNED, the only conversions needed
918 are those involving FLOAT/DOUBLE, and those
919 from LONG to INT and ULONG to UNSIGNED */
920
921 if( t != t1 ) p->left = makety( p->left, tu, 0, (int)tu );
922
923 if( t != t2 || o==CAST ) p->right = makety( p->right, tu, 0, (int)tu );
924
925 if( asgop(o) ){
926 p->type = p->left->type;
927 p->cdim = p->left->cdim;
928 p->csiz = p->left->csiz;
929 }
930 else if( !logop(o) ){
931 p->type = tu;
932 p->cdim = 0;
933 p->csiz = t;
934 }
935
936 if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
937
938 return(p);
939 }
940
941NODE *
942makety( p, t, d, s ) register NODE *p; TWORD t; {
943 /* make p into type t by inserting a conversion */
944
945 if( p->type == ENUMTY && p->op == ICON ) econvert(p);
946 if( t == p->type ){
947 p->cdim = d;
948 p->csiz = s;
949 return( p );
950 }
951
952 if( t & TMASK ){
953 /* non-simple type */
954 return( block( PCONV, p, NIL, t, d, s ) );
955 }
956
957 if( p->op == ICON ){
958 if( t==DOUBLE||t==FLOAT ){
959 p->op = FCON;
960 if( ISUNSIGNED(p->type) ){
961 p->dval = /* (unsigned CONSZ) */ p->lval;
962 }
963 else {
964 p->dval = p->lval;
965 }
966
967 p->type = p->csiz = t;
968 return( clocal(p) );
969 }
970 }
971
972 return( block( SCONV, p, NIL, t, d, s ) );
973
974 }
975
976NODE *
977block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
978
979 register NODE *p;
980
981 p = talloc();
982 p->op = o;
983 p->left = l;
984 p->right = r;
985 p->type = t;
986 p->cdim = d;
987 p->csiz = s;
988 return(p);
989 }
990
991icons(p) register NODE *p; {
992 /* if p is an integer constant, return its value */
993 int val;
994
995 if( p->op != ICON ){
996 uerror( "constant expected");
997 val = 1;
998 }
999 else {
1000 val = p->lval;
1001 if( val != p->lval ) uerror( "constant too big for cross-compiler" );
1002 }
1003 tfree( p );
1004 return(val);
1005 }
1006
1007/* the intent of this table is to examine the
1008 operators, and to check them for
1009 correctness.
1010
1011 The table is searched for the op and the
1012 modified type (where this is one of the
1013 types INT (includes char and short), LONG,
1014 DOUBLE (includes FLOAT), and POINTER
1015
1016 The default action is to make the node type integer
1017
1018 The actions taken include:
1019 PUN check for puns
1020 CVTL convert the left operand
1021 CVTR convert the right operand
1022 TYPL the type is determined by the left operand
1023 TYPR the type is determined by the right operand
1024 TYMATCH force type of left and right to match, by inserting conversions
1025 PTMATCH like TYMATCH, but for pointers
1026 LVAL left operand must be lval
1027 CVTO convert the op
1028 NCVT do not convert the operands
1029 OTHER handled by code
1030 NCVTR convert the left operand, not the right...
1031
1032 */
1033
1034# define MINT 01 /* integer */
1035# define MDBI 02 /* integer or double */
1036# define MSTR 04 /* structure */
1037# define MPTR 010 /* pointer */
1038# define MPTI 020 /* pointer or integer */
1039# define MENU 040 /* enumeration variable or member */
1040
1041opact( p ) NODE *p; {
1042
1043 register mt12, mt1, mt2, o;
1044
1045 mt12 = 0;
1046
1047 switch( optype(o=p->op) ){
1048
1049 case BITYPE:
1050 mt12=mt2 = moditype( p->right->type );
1051 case UTYPE:
1052 mt12 &= (mt1 = moditype( p->left->type ));
1053
1054 }
1055
1056 switch( o ){
1057
1058 case NAME :
1059 case STRING :
1060 case ICON :
1061 case FCON :
1062 case CALL :
1063 case UNARY CALL:
1064 case UNARY MUL:
1065 { return( OTHER ); }
1066 case UNARY MINUS:
1067 if( mt1 & MDBI ) return( TYPL );
1068 break;
1069
1070 case COMPL:
1071 if( mt1 & MINT ) return( TYPL );
1072 break;
1073
1074 case UNARY AND:
1075 { return( NCVT+OTHER ); }
1076 case INIT:
1077 case CM:
1078 case NOT:
1079 case CBRANCH:
1080 case ANDAND:
1081 case OROR:
1082 return( 0 );
1083
1084 case MUL:
1085 case DIV:
1086 if( mt12 & MDBI ) return( TYMATCH );
1087 break;
1088
1089 case MOD:
1090 case AND:
1091 case OR:
1092 case ER:
1093 if( mt12 & MINT ) return( TYMATCH );
1094 break;
1095
1096 case LS:
1097 case RS:
1098 if( mt12 & MINT ) return( TYPL+OTHER );
1099 break;
1100
1101 case EQ:
1102 case NE:
1103 case LT:
1104 case LE:
1105 case GT:
1106 case GE:
1107 if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
1108 if( mt12 & MDBI ) return( TYMATCH+CVTO );
1109 else if( mt12 & MPTR ) return( PTMATCH+PUN );
1110 else if( mt12 & MPTI ) return( PTMATCH+PUN );
1111 else break;
1112
1113 case QUEST:
1114 case COMOP:
1115 if( mt2&MENU ) return( TYPR+NCVTR );
1116 return( TYPR );
1117
1118 case STREF:
1119 return( NCVT+OTHER );
1120
1121 case FORCE:
1122 return( TYPL );
1123
1124 case COLON:
1125 if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
1126 else if( mt12 & MDBI ) return( TYMATCH );
1127 else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1128 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1129 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1130 else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1131 break;
1132
1133 case ASSIGN:
1134 case RETURN:
1135 if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1136 case CAST:
1137 if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
1138 else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
1139 else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
1140 else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1141 break;
1142
1143 case ASG LS:
1144 case ASG RS:
1145 if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1146 break;
1147
1148 case ASG MUL:
1149 case ASG DIV:
1150 if( mt12 & MDBI ) return( LVAL+TYMATCH );
1151 break;
1152
1153 case ASG MOD:
1154 case ASG AND:
1155 case ASG OR:
1156 case ASG ER:
1157 if( mt12 & MINT ) return( LVAL+TYMATCH );
1158 break;
1159
1160 case ASG PLUS:
1161 case ASG MINUS:
1162 case INCR:
1163 case DECR:
1164 if( mt12 & MDBI ) return( TYMATCH+LVAL );
1165 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1166 break;
1167
1168 case MINUS:
1169 if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1170 if( mt2 & MPTR ) break;
1171 case PLUS:
1172 if( mt12 & MDBI ) return( TYMATCH );
1173 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1174 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1175
1176 }
1177 uerror( "operands of %s have incompatible types", opst[o] );
1178 return( NCVT );
1179 }
1180
1181moditype( ty ) TWORD ty; {
1182
1183 switch( ty ){
1184
1185 case ENUMTY:
1186 case MOETY:
1187 return( MENU );
1188
1189 case STRTY:
1190 case UNIONTY:
1191 return( MSTR );
1192
1193 case CHAR:
1194 case SHORT:
1195 case UCHAR:
1196 case USHORT:
1197 return( MINT|MDBI );
1198 case UNSIGNED:
1199 case ULONG:
1200 case INT:
1201 case LONG:
1202 return( MINT|MDBI|MPTI );
1203 case FLOAT:
1204 case DOUBLE:
1205 return( MDBI );
1206 default:
1207 return( MPTR|MPTI );
1208
1209 }
1210 }
1211
1212NODE *
1213doszof( p ) register NODE *p; {
1214 /* do sizeof p */
1215 int i;
1216
1217 /* whatever is the meaning of this if it is a bitfield? */
1218 i = tsize( p->type, p->cdim, p->csiz )/SZCHAR;
1219
1220 tfree(p);
1221 if( i <= 0 ) werror( "sizeof returns 0" );
1222 return( bcon( i ) );
1223 }
1224
1225eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1226 register ty;
1227
1228 *a = *b = down+1;
1229 while( down > 1 ){
1230 printf( "\t" );
1231 down -= 2;
1232 }
1233 if( down ) printf( " " );
1234
1235 ty = optype( p->op );
1236
1237 printf("%o) %s, ", p, opst[p->op] );
1238 if( ty == LTYPE ){
1239 printf( CONFMT, p->lval );
1240 printf( ", %d, ", p->rval );
1241 }
1242 tprint( p->type );
1243 printf( ", %d, %d\n", p->cdim, p->csiz );
1244 }
1245
1246prtdcon( p ) register NODE *p; {
1247 int i;
1248
1249 if( p->op == FCON ){
1250 locctr( DATA );
1251 defalign( ALDOUBLE );
1252 deflab( i = getlab() );
1253 fincode( p->dval, SZDOUBLE );
1254 p->lval = 0;
1255 p->rval = -i;
1256 p->type = DOUBLE;
1257 p->op = NAME;
1258 }
1259 }
1260
1261
1262int edebug = 0;
1263ecomp( p ) register NODE *p; {
1264 if( edebug ) fwalk( p, eprint, 0 );
1265 if( !reached ){
1266 werror( "statement not reached" );
1267 reached = 1;
1268 }
1269 p = optim(p);
1270 walkf( p, prtdcon );
1271 locctr( PROG );
1272 ecode( p );
1273 tfree(p);
1274 }
1275
1276# ifdef STDPRTREE
1277# ifndef ONEPASS
1278
1279prtree(p) register NODE *p; {
1280
1281 register struct symtab *q;
1282 register ty;
1283
1284# ifdef MYPRTREE
1285 MYPRTREE(p); /* local action can be taken here; then return... */
1286#endif
1287
1288 ty = optype(p->op);
1289
1290 printf( "%d\t", p->op );
1291
1292 if( ty == LTYPE ) {
1293 printf( CONFMT, p->lval );
1294 printf( "\t" );
1295 }
1296 if( ty != BITYPE ) {
1297 if( p->op == NAME || p->op == ICON ) printf( "0\t" );
1298 else printf( "%d\t", p->rval );
1299 }
1300
1301 printf( "%o\t", p->type );
1302
1303 /* handle special cases */
1304
1305 switch( p->op ){
1306
1307 case NAME:
1308 case ICON:
1309 /* print external name */
1310 if( p->rval == NONAME ) printf( "\n" );
1311 else if( p->rval >= 0 ){
1312 q = &stab[p->rval];
1313 printf( "%s\n", exname(q->sname) );
1314 }
1315 else { /* label */
1316 printf( LABFMT, -p->rval );
1317 }
1318 break;
1319
1320 case STARG:
1321 case STASG:
1322 case STCALL:
1323 case UNARY STCALL:
1324 /* print out size */
1325 /* use lhs size, in order to avoid hassles with the structure `.' operator */
1326
1327 /* note: p->left not a field... */
1328 printf( CONFMT, (CONSZ) tsize( STRTY, p->left->cdim, p->left->csiz ) );
1329 printf( "\t%d\t\n", talign( STRTY, p->left->csiz ) );
1330 break;
1331
1332 default:
1333 printf( "\n" );
1334 }
1335
1336 if( ty != LTYPE ) prtree( p->left );
1337 if( ty == BITYPE ) prtree( p->right );
1338
1339 }
1340
1341# else
1342
1343p2tree(p) register NODE *p; {
1344 register ty;
1345
1346# ifdef MYP2TREE
1347 MYP2TREE(p); /* local action can be taken here; then return... */
1348# endif
1349
1350 ty = optype(p->op);
1351
1352 switch( p->op ){
1353
1354 case NAME:
1355 case ICON:
1356 if( p->rval == NONAME ) p->name[0] = '\0';
1357 else if( p->rval >= 0 ){ /* copy name from exname */
1358 register char *cp;
1359 register i;
1360 cp = exname( stab[p->rval].sname );
1361 for( i=0; i<NCHNAM; ++i ) p->name[i] = *cp++;
1362 }
1363 else sprintf( p->name, LABFMT, -p->rval );
1364 break;
1365
1366 case STARG:
1367 case STASG:
1368 case STCALL:
1369 case UNARY STCALL:
1370 /* set up size parameters */
1371 p->stsize = (tsize(STRTY,p->left->cdim,p->left->csiz)+SZCHAR-1)/SZCHAR;
1372 p->stalign = talign(STRTY,p->left->csiz)/SZCHAR;
1373 break;
1374
1375 case REG:
1376 rbusy( p->rval, p->type );
1377 default:
1378 p->name[0] = '\0';
1379 }
1380
1381 p->rall = NOPREF;
1382
1383 if( ty != LTYPE ) p2tree( p->left );
1384 if( ty == BITYPE ) p2tree( p->right );
1385 }
1386
1387# endif
1388# endif