Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030126223556

Diff

Diff from 1.15 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/ccom/trees.c

Annotated File View

ragge
1.2
1 #if 0
ragge
1.1
2 static char *sccsid ="@(#)trees.c       4.37 (Berkeley) 6/18/90";
3 #endif
4
5 # include "pass1.h"
ragge
1.9
6 # include "pass2.h"     /* for NOPREF */
ragge
1.1
7
8 # include <setjmp.h>
9
10 int bdebug = 0;
11 int adebug = 0;
ragge
1.2
12 extern int ddebug;
ragge
1.1
13
ragge
1.2
14 void chkpun(NODE *p);
15 int opact(NODE *p);
16 int chkstr(intintTWORD);
17 int moditype(TWORD);
18
19 /* corrections when in violation of lint */
ragge
1.1
20
21 /*      some special actions, used in finding the type of nodes */
22 # define NCVT 01
23 # define PUN 02
24 # define TYPL 04
25 # define TYPR 010
26 # define TYMATCH 040
27 # define LVAL 0100
28 # define CVTO 0200
29 # define CVTL 0400
30 # define CVTR 01000
31 # define PTMATCH 02000
32 # define OTHER 04000
33 # define NCVTR 010000
34
35 #ifndef BUG1
ragge
1.2
36 static void
37 printact(NODE *tint acts)
ragge
1.1
38 {
39         static struct actions {
40                 int     a_bit;
41                 char    *a_name;
42         } actions[] = {
43                 { PUN,          "PUN" },
44                 { CVTL,         "CVTL" },
45                 { CVTR,         "CVTR" },
46                 { TYPL,         "TYPL" },
47                 { TYPR,         "TYPR" },
48                 { TYMATCH,      "TYMATCH" },
49                 { PTMATCH,      "PTMATCH" },
50                 { LVAL,         "LVAL" },
51                 { CVTO,         "CVTO" },
52                 { NCVT,         "NCVT" },
53                 { OTHER,        "OTHER" },
54                 { NCVTR,        "NCVTR" },
55                 { 0 }
56         };
57         register struct actions *p;
58         char *sep = " ";
59
60         printf("actions");
61         for (p = actionsp->a_namep++)
62                 if (p->a_bit & acts) {
63                         printf("%s%s"sepp->a_name);
64                         sep = "|";
65                 }
66         if (!bdebug) {
67                 printf(" for:\n");
68                 fwalk(teprint0);
69         } else
70                 putchar('\n');
71 }
72 #endif
73
74 /* node conventions:
75
76         NAME:   rval>0 is stab index for external
77                 rval<0 is -inlabel number
78                 lval is offset in bits
79         ICON:   lval has the value
80                 rval has the STAB index, or - label number,
81                         if a name whose address is in the constant
82                 rval = NONAME means no name
83         REG:    rval is reg. identification cookie
84
85         */
86
87 NODE *
ragge
1.2
88 buildtree(int oNODE *lNODE *r)
89 {
90         NODE *p, *q;
91         int actions;
92         int opty;
93         struct symtab *sp;
94         NODE *lr, *ll;
ragge
1.1
95         int i;
96
97 # ifndef BUG1
ragge
1.2
98         if (bdebug)
99                 printf("buildtree(%s, %p, %p)\n"opst[o], lr);
ragge
1.1
100 # endif
101         opty = optype(o);
102
103         /* check for constants */
104
105         ifopty == UTYPE && l->in.op == ICON ){
106
107                 switcho ){
108
109                 case NOT:
110                 case UNARY MINUS:
111                 case COMPL:
112                         ifconvallol ) ) return(l);
113                         break;
114
115                         }
116                 }
117
118         else ifopty == UTYPE && (l->in.op == FCON || l->in.op == DCON) ){
119
120                 switcho ){
121
122                 case NOT:
123                         ifl->in.op == FCON )
124                                 l->tn.lval = l->fpn.fval == 0.0;
125                         else
126                                 l->tn.lval = l->dpn.dval == 0.0;
127                         l->tn.rval = NONAME;
128                         l->in.op = ICON;
129                         l->fn.csiz = l->in.type = INT;
130                         l->fn.cdim = 0;
131                         return(l);
132                 case UNARY MINUS:
133                         ifl->in.op == FCON )
134                                 l->fpn.fval = -l->fpn.fval;
135                         else
136                                 l->dpn.dval = -l->dpn.dval;
137                         return(l);
138                         }
139                 }
140
141         else ifo==QUEST && l->in.op==ICON ) {
142                 l->in.op = FREE;
143                 r->in.op = FREE;
144                 ifl->tn.lval ){
145                         tfreer->in.right );
146                         returnr->in.left );
147                         }
148                 else {
149                         tfreer->in.left );
150                         returnr->in.right );
151                         }
152                 }
153
154         else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
155
156         else ifopty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
157
158                 switcho ){
159
160                 case ULT:
161                 case UGT:
162                 case ULE:
163                 case UGE:
164                 case LT:
165                 case GT:
166                 case LE:
167                 case GE:
168                 case EQ:
169                 case NE:
170                         ifl->in.type == ENUMTY && r->in.type == ENUMTY ){
171                                 p = blockolrINT0INT );
172                                 chkpunp );
173                                 p->in.op = FREE;
174                                 }
175
176                 case ANDAND:
177                 case OROR:
178                 case CBRANCH:
179
180                 ccwarn:
181
182                 case PLUS:
183                 case MINUS:
184                 case MUL:
185                 case DIV:
186                 case MOD:
187                 case AND:
188                 case OR:
189                 case ER:
190                 case LS:
191                 case RS:
192                         ifconvallor ) ) {
193                                 r->in.op = FREE;
194                                 return(l);
195                                 }
196                         break;
197                         }
198                 }
199         else if (opty == BITYPE &&
200                 (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
201                 (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
202                         if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
203                                 extern int fpe_count;
204                                 extern jmp_buf gotfpe;
205
206                                 fpe_count = 0;
207                                 if (setjmp(gotfpe))
208                                         goto treatfpe;
209                                 if (l->in.op == ICON)
210                                         l->dpn.dval = l->tn.lval;
211                                 else if (l->in.op == FCON)
212                                         l->dpn.dval = l->fpn.fval;
213                                 if (r->in.op == ICON)
214                                         r->dpn.dval = r->tn.lval;
215                                 else if (r->in.op == FCON)
216                                         r->dpn.dval = r->fpn.fval;
217                                 switch (o) {
218
219                                 case PLUS:
220                                         l->dpn.dval += r->dpn.dval;
221                                         break;
222
223                                 case MINUS:
224                                         l->dpn.dval -= r->dpn.dval;
225                                         break;
226
227                                 case MUL:
228                                         l->dpn.dval *= r->dpn.dval;
229                                         break;
230
231                                 case DIV:
232                                         if (r->dpn.dval == 0)
233                                                 uerror("division by 0.");
234                                         else
235                                                 l->dpn.dval /= r->dpn.dval;
236                                         break;
237                                         }
238                         treatfpe:
239                                 if (fpe_count > 0) {
240                                         uerror("floating point exception in constant expression");
241                                         l->dpn.dval = 1.0/* Fairly harmless */
242                                         }
243                                 fpe_count = -1;
244                                 l->in.op = DCON;
245                                 l->in.type = l->fn.csiz = DOUBLE;
246                                 r->in.op = FREE;
247                                 return (l);
248                         }
249                 }
250
251         /* it's real; we must make a new node */
252
253         p = blockolrINT0INT );
254
255         actions = opact(p);
256 #ifndef BUG1
257         if (adebug)
258                 printact(pactions);
259 #endif
260
261         ifactions&LVAL ){ /* check left descendent */
262                 ifnotlval(p->in.left) ) {
263                         uerror"illegal lvalue operand of assignment operator" );
264                         }
265                 }
266
267         ifactions & NCVTR ){
268                 p->in.left = pconvertp->in.left );
269                 }
270         else if( !(actions & NCVT ) ){
271                 switchopty ){
272
273                 case BITYPE:
274                         p->in.right = pconvertp->in.right );
275                 case UTYPE:
276                         p->in.left = pconvertp->in.left );
277
278                         }
279                 }
280
ragge
1.7
281         if ((actions&PUN) && (o!=CAST||cflag))
ragge
1.1
282                 chkpun(p);
283
284         ifactions & (TYPL|TYPR) ){
285
286                 q = (actions&TYPL) ? p->in.left : p->in.right;
287
288                 p->in.type = q->in.type;
289                 p->fn.cdim = q->fn.cdim;
290                 p->fn.csiz = q->fn.csiz;
291                 }
292
293         ifactions & CVTL ) p = convertpCVTL );
294         ifactions & CVTR ) p = convertpCVTR );
295         ifactions & TYMATCH ) p = tymatch(p);
296         ifactions & PTMATCH ) p = ptmatch(p);
297
298         ifactions & OTHER ){
299                 l = p->in.left;
300                 r = p->in.right;
301
302                 switch(o){
303
304                 case NAME:
305                         sp = &stab[idname];
306                         ifsp->stype == UNDEF ){
307                                 uerror"%s undefined"sp->sname );
308                                 /* make p look reasonable */
309                                 p->in.type = p->fn.csiz = INT;
310                                 p->fn.cdim = 0;
311                                 p->tn.rval = idname;
312                                 p->tn.lval = 0;
313                                 defidpSNULL );
314                                 break;
315                                 }
316                         p->in.type = sp->stype;
317                         p->fn.cdim = sp->dimoff;
318                         p->fn.csiz = sp->sizoff;
319                         p->tn.lval = 0;
320                         p->tn.rval = idname;
321                         /* special case: MOETY is really an ICON... */
322                         ifp->in.type == MOETY ){
323                                 p->tn.rval = NONAME;
324                                 p->tn.lval = sp->offset;
325                                 p->fn.cdim = 0;
326                                 p->in.type = ENUMTY;
327                                 p->in.op = ICON;
328                                 }
329                         break;
330
331                 case ICON:
332                         p->in.type = INT;
333                         p->fn.cdim = 0;
334                         p->fn.csiz = INT;
335                         break;
336
337                 case STRING:
338                         p->in.op = NAME;
339                         p->in.type = CHAR+ARY;
340                         p->tn.lval = 0;
341                         p->tn.rval = NOLAB;
342                         p->fn.cdim = curdim;
343                         p->fn.csiz = CHAR;
344                         break;
345
346                 case FCON:
347                         p->tn.lval = 0;
348                         p->tn.rval = 0;
349                         p->in.type = FLOAT;
350                         p->fn.cdim = 0;
351                         p->fn.csiz = FLOAT;
352                         break;
353
354                 case DCON:
355                         p->tn.lval = 0;
356                         p->tn.rval = 0;
357                         p->in.type = DOUBLE;
358                         p->fn.cdim = 0;
359                         p->fn.csiz = DOUBLE;
360                         break;
361
362                 case STREF:
363                         /* p->x turned into *(p+offset) */
364                         /* rhs must be a name; check correctness */
365
366                         i = r->tn.rval;
367                         ifi<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
368                                 uerror"member of structure or union required" );
369                                 }else
370                         /* if this name is non-unique, find right one */
371                         ifstab[i].sflags & SNONUNIQ &&
372                                 (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
373                                 (l->fn.csiz +1) >= 0 ){
374                                 /* nonunique name && structure defined */
375                                 char * memnam, * tabnam;
376                                 int j;
377                                 int memi;
378                                 j=dimtab[l->fn.csiz+1];
379                                 for( ; (memi=dimtab[j]) >= 0; ++j ){
380                                         tabnam = stab[memi].sname;
381                                         memnam = stab[i].sname;
382 # ifndef BUG1
383                                         ifddebug>1 ){
384                                                 printf("member %s==%s?\n",
385                                                         memnamtabnam);
386                                                 }
387 # endif
388                                         ifstab[memi].sflags & SNONUNIQ ){
389                                                 if (memnam != tabnam)
390                                                         goto next;
391                                                 r->tn.rval = i = memi;
392                                                 break;
393                                                 }
394                                         nextcontinue;
395                                         }
396                                 ifmemi < 0 )
397                                         uerror("illegal member use: %s",
398                                                 stab[i].sname);
399                                 }
400                         else {
ragge
1.2
401                                 int j;
ragge
1.1
402                                 ifl->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
403                                         ifstab[i].sflags & SNONUNIQ ){
404                                                 uerror"nonunique name demands struct/union or struct/union pointer" );
405                                                 }
406                                         else werror"struct/union or struct/union pointer required" );
407                                         }
408                                 else if( (j=l->fn.csiz+1)<0 ) cerror"undefined structure or union" );
409                                 else if( !chkstridimtab[j], DECREF(l->in.type) ) ){
410                                         werror"illegal member use: %s"stab[i].sname );
411                                         }
412                                 }
413
414                         p = strefp );
415                         break;
416
417                 case UNARY MUL:
418                         ifl->in.op == UNARY AND ){
419                                 p->in.op = l->in.op = FREE;
420                                 p = l->in.left;
421                                 }
422                         if( !ISPTR(l->in.type))uerror("illegal indirection");
423                         p->in.type = DECREF(l->in.type);
424                         p->fn.cdim = l->fn.cdim;
425                         p->fn.csiz = l->fn.csiz;
426                         break;
427
428                 case UNARY AND:
429                         switchl->in.op ){
430
431                         case UNARY MUL:
432                                 p->in.op = l->in.op = FREE;
433                                 p = l->in.left;
434                         case NAME:
435                                 p->in.type = INCREFl->in.type );
436                                 p->fn.cdim = l->fn.cdim;
437                                 p->fn.csiz = l->fn.csiz;
438                                 break;
439
440                         case COMOP:
441                                 lr = buildtreeUNARY ANDl->in.rightNIL );
442                                 p->in.op = l->in.op = FREE;
443                                 p = buildtreeCOMOPl->in.leftlr );
444                                 break;
445
446                         case QUEST:
447                                 lr = buildtreeUNARY ANDl->in.right->in.rightNIL );
448                                 ll = buildtreeUNARY ANDl->in.right->in.leftNIL );
449                                 p->in.op = l->in.op = l->in.right->in.op = FREE;
450                                 p = buildtreeQUESTl->in.leftbuildtreeCOLONlllr ) );
451                                 break;
452
453 # ifdef ADDROREG
454                         case OREG:
455                                 /* OREG was built in clocal()
456                                  * for an auto or formal parameter
457                                  * now its address is being taken
458                                  * local code must unwind it
459                                  * back to PLUS/MINUS REG ICON
460                                  * according to local conventions
461                                  */
462                                 p->in.op = FREE;
463                                 p = addroregl );
464                                 break;
465
466 # endif
467                         default:
468                                 uerror"unacceptable operand of &" );
469                                 break;
470                                 }
471                         break;
472
473                 case LS:
474                 case RS:
475                         ifl->in.type == CHAR || l->in.type == SHORT )
476                                 p->in.type = INT;
477                         else ifl->in.type == UCHAR || l->in.type == USHORT )
478                                 p->in.type = UNSIGNED;
479                         else
480                                 p->in.type = l->in.type;
481                 case ASG LS:
482                 case ASG RS:
483                         ifr->in.type != INT )
484                                 p->in.right = r = makety(rINT0INT );
485                         break;
486
487                 case RETURN:
488                 case ASSIGN:
489                 case CAST:
490                         /* structure assignment */
491                         /* take the addresses of the two sides; then make an
ragge
1.2
492                          * operator using STASG and
493                          * the addresses of left and right */
ragge
1.1
494
495                         {
ragge
1.2
496                                 TWORD t;
497                                 int ds;
ragge
1.1
498
499                                 ifl->fn.csiz != r->fn.csiz ) uerror"assignment of different structures" );
500
501                                 r = buildtreeUNARY ANDrNIL );
502                                 t = r->in.type;
503                                 d = r->fn.cdim;
504                                 s = r->fn.csiz;
505
506                                 l = blockSTASGlrtds );
507
508                                 ifo == RETURN ){
509                                         p->in.op = FREE;
510                                         p = l;
511                                         break;
512                                         }
513
514                                 p->in.op = UNARY MUL;
515                                 p->in.left = l;
516                                 p->in.right = NIL;
517                                 break;
518                                 }
519                 case COLON:
520                         /* structure colon */
521
522                         ifl->fn.csiz != r->fn.csiz ) uerror"type clash in conditional" );
523                         break;
524
525                 case CALL:
526                         p->in.right = r = fixargsp->in.right );
527                 case UNARY CALL:
528                         if( !ISPTR(l->in.type)) uerror("illegal function");
529                         p->in.type = DECREF(l->in.type);
530                         if( !ISFTN(p->in.type)) uerror("illegal function");
531                         p->in.type = DECREFp->in.type );
532                         p->fn.cdim = l->fn.cdim;
533                         p->fn.csiz = l->fn.csiz;
534                         ifl->in.op == UNARY AND && l->in.left->in.op == NAME &&
535                                 l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
536                                 ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
537                                 p->in.op += (FORTCALL-CALL);
538                                 }
539                         ifp->in.type == STRTY || p->in.type == UNIONTY ){
540                                 /* function returning structure */
541                                 /*  make function really return ptr to str., with * */
542
543                                 p->in.op += STCALL-CALL;
544                                 p->in.type = INCREFp->in.type );
545                                 p = buildtreeUNARY MULpNIL );
546
547                                 }
548                         break;
549
550                 default:
551                         cerror"other code %d"o );
552                         }
553
554                 }
555
ragge
1.11
556         /*
557          * Allow (void)0 casts.
558          * XXX - anything on the right side must be possible to cast.
559          * XXX - remove void types further on.
560          */
561         if (p->in.op == CAST && p->in.type == UNDEF &&
562             p->in.right->in.op == ICON)
563                 p->in.right->in.type = UNDEF;
564
ragge
1.1
565         ifactions & CVTO ) p = oconvert(p);
566         p = clocal(p);
567
568 # ifndef BUG1
569         ifbdebug ) fwalkpeprint0 );
570 # endif
571
572         return(p);
573
574         }
575
576 int fpe_count = -1;
577 jmp_buf gotfpe;
578
ragge
1.2
579 void fpe(int);
ragge
1.1
580 void
ragge
1.2
581 fpe(int a)
582 {
ragge
1.1
583         if (fpe_count < 0)
584                 cerror("floating point exception");
585         ++fpe_count;
586         longjmp(gotfpe1);
ragge
1.2
587 }
ragge
1.1
588
589 /*
590  * Rewrite arguments in a function call.
591  * Structure arguments are massaged, single
592  * precision floating point constants are
593  * cast to double (to eliminate convert code).
594  */
595 NODE *
596 fixargsp ) register NODE *p;  {
597         int o = p->in.op;
598
599         ifo == CM ){
600                 p->in.left = fixargsp->in.left );
601                 p->in.right = fixargsp->in.right );
602                 returnp );
603                 }
604
605         ifp->in.type == STRTY || p->in.type == UNIONTY ){
606                 p = blockSTARGpNILp->in.typep->fn.cdimp->fn.csiz );
607                 p->in.left = buildtreeUNARY ANDp->in.leftNIL );
608                 p = clocal(p);
609                 }
610         else ifo == FCON )
611                 p = makety(pDOUBLE00);
612         returnp );
ragge
1.2
613 }
ragge
1.1
614
ragge
1.2
615 /*
616  * is the MOS or MOU at stab[i] OK for strict reference by a ptr
617  * i has been checked to contain a MOS or MOU
618  * j is the index in dimtab of the members...
619  */
620 int
621 chkstr(int iint jTWORD type)
622 {
ragge
1.1
623         int kkk;
624
625         extern int ddebug;
626
627 # ifndef BUG1
ragge
1.15
628         if (ddebug > 1)
629                 printf("chkstr( %s(%d), %d )\n"stab[i].snameij);
ragge
1.1
630 # endif
ragge
1.15
631         if ((k = j) < 0)
632                 uerror("undefined structure or union");
ragge
1.1
633         else {
ragge
1.15
634                 for (; (kk = dimtab[k] ) >= 0; ++k) {
635                         if (kk >= SYMTSZ) {
ragge
1.1
636                                 cerror"gummy structure" );
637                                 return(1);
ragge
1.15
638                         }
639                         if (kk == i)
640                                 return(1);
641                         switch(stab[kk].stype) {
ragge
1.1
642
643                         case STRTY:
644                         case UNIONTY:
ragge
1.15
645                                 if (type == STRTY)
646                                         continue;  /* no recursive looking for strs */
ragge
1.1
647                         }
648                 }
ragge
1.15
649         }
650         return(0);
ragge
1.2
651 }
ragge
1.1
652
ragge
1.2
653 /*
654  * apply the op o to the lval part of p; if binary, rhs is val
655  * works only on integer constants
656  */
657 int
658 conval(NODE *pint oNODE *q)
659 {
ragge
1.1
660         int iu;
661         CONSZ val;
662         TWORD utype;
663
664         val = q->tn.lval;
665         u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
666         ifu && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
667
668         ifp->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
669         ifq->tn.rval != NONAME && o!=PLUS ) return(0);
670         ifp->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
671
672         /* usual type conversions -- handle casts of constants */
673 #define ISLONG(t)       ((t) == LONG || (t) == ULONG)
ragge
1.6
674 #define ISLONGLONG(t)   ((t) == LONGLONG || (t) == ULONGLONG)
ragge
1.1
675         if (ISLONG(p->in.type) || ISLONG(q->in.type))
676                 utype = u ? ULONG : LONG;
ragge
1.6
677         else if (ISLONGLONG(p->in.type) || ISLONGLONG(q->in.type))
678                 utype = u ? ULONGLONG : LONGLONG;
ragge
1.1
679         else
680                 utype = u ? UNSIGNED : INT;
681         if( !ISPTR(p->in.type) && p->in.type != utype )
682                 p = makety(putype0, (int)utype);
683         ifq->in.type != utype )
684                 q = makety(qutype0, (int)utype);
685
686         switcho ){
687
688         case PLUS:
689                 p->tn.lval += val;
690                 ifp->tn.rval == NONAME ){
691                         p->tn.rval = q->tn.rval;
692                         p->in.type = q->in.type;
693                         }
694                 break;
695         case MINUS:
696                 p->tn.lval -= val;
697                 break;
698         case MUL:
699                 p->tn.lval *= val;
700                 break;
701         case DIV:
702                 ifval == 0 ) uerror"division by 0" );
703                 else if ( u ) p->tn.lval = (unsignedp->tn.lval / val;
704                 else p->tn.lval /= val;
705                 break;
706         case MOD:
707                 ifval == 0 ) uerror"division by 0" );
708                 else if ( u ) p->tn.lval = (unsignedp->tn.lval % val;
709                 else p->tn.lval %= val;
710                 break;
711         case AND:
712                 p->tn.lval &= val;
713                 break;
714         case OR:
715                 p->tn.lval |= val;
716                 break;
717         case ER:
718                 p->tn.lval ^= val;
719                 break;
720         case LS:
721                 i = val;
722                 p->tn.lval = p->tn.lval << i;
723                 break;
724         case RS:
725                 i = val;
726                 if ( u ) p->tn.lval = (unsignedp->tn.lval >> i;
727                 else p->tn.lval = p->tn.lval >> i;
728                 break;
729
730         case UNARY MINUS:
731                 p->tn.lval = - p->tn.lval;
732                 break;
733         case COMPL:
734                 p->tn.lval = ~p->tn.lval;
735                 break;
736         case NOT:
737                 p->tn.lval = !p->tn.lval;
738                 break;
739         case LT:
740                 p->tn.lval = p->tn.lval < val;
741                 break;
742         case LE:
743                 p->tn.lval = p->tn.lval <= val;
744                 break;
745         case GT:
746                 p->tn.lval = p->tn.lval > val;
747                 break;
748         case GE:
749                 p->tn.lval = p->tn.lval >= val;
750                 break;
751         case ULT:
752                 p->tn.lval = p->tn.lval < (unsignedval;
753                 break;
754         case ULE:
755                 p->tn.lval = p->tn.lval <= (unsignedval;
756                 break;
757         case UGT:
758                 p->tn.lval = p->tn.lval > (unsignedval;
759                 break;
760         case UGE:
761                 p->tn.lval = p->tn.lval >= (unsignedval;
762                 break;
763         case EQ:
764                 p->tn.lval = p->tn.lval == val;
765                 break;
766         case NE:
767                 p->tn.lval = p->tn.lval != val;
768                 break;
769         default:
770                 return(0);
771                 }
772         return(1);
773         }
774
ragge
1.7
775 /*
776  * Checks p for the existance of a pun.  This is called when the op of p
777  * is ASSIGN, RETURN, CAST, COLON, or relational.
778  * One case is when enumerations are used: this applies only to lint.
779  * In the other case, one operand is a pointer, the other integer type
780  * we check that this integer is in fact a constant zero...
781  * in the case of ASSIGN, any assignment of pointer to integer is illegal
782  * this falls out, because the LHS is never 0.
783  */
ragge
1.2
784 void
ragge
1.7
785 chkpun(NODE *p)
786 {
ragge
1.2
787         NODE *q;
788         int t1t2d1d2ref1ref2;
ragge
1.1
789
790         t1 = p->in.left->in.type;
791         t2 = p->in.right->in.type;
792
ragge
1.7
793         /* check for enumerations */
794         if (t1==ENUMTY || t2==ENUMTY) {
ragge
1.1
795                 /* rob pike says this is obnoxious...
796                 if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
797                         werror( "comparison of enums" ); */
ragge
1.7
798                 if (t1==ENUMTY && t2==ENUMTY) {
799                         if (p->in.left->fn.csiz!=p->in.right->fn.csiz)
800                                 werror("enumeration type clash, "
801                                     "operator %s"opst[p->in.op]);
ragge
1.1
802                         return;
803                 }
ragge
1.7
804                 if (t1 == ENUMTY)
805                         t1 = INT;
806                 if (t2 == ENUMTY)
807                         t2 = INT;
808         }
ragge
1.1
809
810         ref1 = ISPTR(t1) || ISARY(t1);
811         ref2 = ISPTR(t2) || ISARY(t2);
812
ragge
1.7
813         if (ref1 ^ ref2) {
814                 if (ref1)
815                         q = p->in.right;
816                 else
817                         q = p->in.left;
818                 if (q->in.op != ICON || q->tn.lval != 0)
819                         werror("illegal combination of pointer "
820                             "and integer, op %s"opst[p->in.op]);
821         } else if (ref1) {
822                 if (t1 == t2) {
823                         if (p->in.left->fn.csiz != p->in.right->fn.csiz) {
ragge
1.5
824                                 werror("illegal structure pointer combination");
ragge
1.1
825                                 return;
ragge
1.5
826                         }
ragge
1.1
827                         d1 = p->in.left->fn.cdim;
828                         d2 = p->in.right->fn.cdim;
ragge
1.7
829                         for (;;) {
830                                 if (ISARY(t1)) {
831                                         if (dimtab[d1] != dimtab[d2]) {
832                                                 werror("illegal array "
833                                                     "size combination");
ragge
1.1
834                                                 return;
ragge
1.5
835                                         }
ragge
1.1
836                                         ++d1;
837                                         ++d2;
ragge
1.5
838                                 } else
ragge
1.7
839                                         if (!ISPTR(t1))
ragge
1.5
840                                                 break;
ragge
1.1
841                                 t1 = DECREF(t1);
842                         }
ragge
1.7
843                 } else if (t1 != INCREF(UNDEF) && t2 != INCREF(UNDEF))
844                         werror("illegal pointer combination");
ragge
1.1
845         }
ragge
1.5
846 }
ragge
1.1
847
848 NODE *
ragge
1.10
849 stref(NODE *p)
850 {
ragge
1.1
851         TWORD t;
852         int dsdscalign;
853         OFFSZ off;
854         register struct symtab *q;
855
856         /* make p->x */
857         /* this is also used to reference automatic variables */
858
859         q = &stab[p->in.right->tn.rval];
860         p->in.right->in.op = FREE;
861         p->in.op = FREE;
ragge
1.10
862         p = pconvert(p->in.left);
ragge
1.1
863
864         /* make p look like ptr to x */
865
ragge
1.10
866         if (!ISPTR(p->in.type))
ragge
1.1
867                 p->in.type = PTR+UNIONTY;
868
ragge
1.10
869         t = INCREF(q->stype);
ragge
1.1
870         d = q->dimoff;
871         s = q->sizoff;
872
ragge
1.10
873         p = makety(ptds);
ragge
1.1
874
875         /* compute the offset to be added */
876
877         off = q->offset;
878         dsc = q->sclass;
879
ragge
1.10
880         if (dsc & FIELD) {  /* normalize offset */
ragge
1.1
881                 align = ALINT;
882                 s = INT;
883                 off = (off/align)*align;
ragge
1.10
884         }
885         if (off != 0)
886                 p = clocal(block(PLUSpoffcon(offtds), tds));
ragge
1.1
887
ragge
1.10
888         p = buildtree(UNARY MULpNIL);
ragge
1.1
889
890         /* if field, build field info */
891
ragge
1.10
892         if (dsc & FIELD) {
893                 p = block(FLDpNILq->stype0q->sizoff);
894                 p->tn.rval = PKFIELD(dsc&FLDSIZq->offset%align);
895         }
ragge
1.1
896
ragge
1.10
897         return(clocal(p));
898 }
ragge
1.1
899
ragge
1.2
900 int
ragge
1.1
901 notlval(pregister NODE *p; {
902
903         /* return 0 if p an lvalue, 1 otherwise */
904
905         again:
906
907         switchp->in.op ){
908
909         case FLD:
910                 p = p->in.left;
911                 goto again;
912
913         case UNARY MUL:
914                 /* fix the &(a=b) bug, given that a and b are structures */
915                 ifp->in.left->in.op == STASG ) return1 );
916                 /* and the f().a bug, given that f returns a structure */
917                 ifp->in.left->in.op == UNARY STCALL ||
918                     p->in.left->in.op == STCALL ) return1 );
919         case NAME:
920         case OREG:
921                 ifISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
922         case REG:
923                 return(0);
924
925         default:
926                 return(1);
927
928                 }
929
930         }
931
932 NODE *
933 bconi ){ /* make a constant node with value i */
934         register NODE *p;
935
936         p = blockICONNILNILINT0INT );
937         p->tn.lval = i;
938         p->tn.rval = NONAME;
939         returnclocal(p) );
940         }
941
942 NODE *
ragge
1.10
943 bpsize(NODE *p)
944 {
945         return(offcon(psize(p), p->in.typep->fn.cdimp->fn.csiz));
946 }
ragge
1.1
947
ragge
1.10
948 /*
949  * p is a node of type pointer; psize returns the
950  * size of the thing pointed to
951  */
ragge
1.1
952 OFFSZ
ragge
1.10
953 psize(NODE *p)
954 {
955
956         if (!ISPTR(p->in.type)) {
957                 uerror("pointer required");
958                 return(SZINT);
959         }
ragge
1.1
960         /* note: no pointers to fields */
ragge
1.10
961         return(tsize(DECREF(p->in.type), p->fn.cdimp->fn.csiz));
962 }
ragge
1.1
963
ragge
1.10
964 /*
965  * convert an operand of p
966  * f is either CVTL or CVTR
967  * operand has type int, and is converted by the size of the other side
968  */
ragge
1.1
969 NODE *
ragge
1.10
970 convert(NODE *pint f)
971 {
972         NODE *q, *r, *s;
ragge
1.1
973
ragge
1.10
974         q = (f == CVTL) ? p->in.left : p->in.right;
ragge
1.1
975
ragge
1.10
976         s = bpsize(f == CVTL ? p->in.right : p->in.left);
977         r = block(PMCONVqsINT0INT);
ragge
1.1
978         r = clocal(r);
ragge
1.13
979         /*
980          * Indexing is only allowed with integer arguments, so insert
981          * SCONV here if arg is not an integer.
982          * XXX - complain?
983          */
984         if (r->in.type != INT)
985                 r = clocal(block(SCONVrNILINT0INT));
ragge
1.10
986         if (f == CVTL)
ragge
1.1
987                 p->in.left = r;
988         else
989                 p->in.right = r;
990         return(p);
ragge
1.10
991 }
ragge
1.1
992
993 #ifndef econvert
ragge
1.2
994 void
ragge
1.1
995 econvertp ) register NODE *p; {
996
997         /* change enums to ints, or appropriate types */
998
999         register TWORD ty;
1000
1001         if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
ragge
1.6
1002                 if (dimtab[p->fn.csiz] == SZCHAR)
1003                         ty = CHAR;
1004                 else if (dimtab[p->fn.csiz] == SZINT)
1005                         ty = INT;
1006                 else if (dimtab[p->fn.csiz] == SZSHORT)
1007                         ty = SHORT;
1008                 else if (dimtab[p->fn.csiz] == SZLONGLONG)
1009                         ty = LONGLONG;
1010                 else
1011                         ty = LONG;
1012                 ty = ctype(ty);
ragge
1.1
1013