Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20020929165221

Diff

Diff from 1.9 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                         ifhflag ) werror"constant argument to NOT" );
111                 case UNARY MINUS:
112                 case COMPL:
113                         ifconvallol ) ) return(l);
114                         break;
115
116                         }
117                 }
118
119         else ifopty == UTYPE && (l->in.op == FCON || l->in.op == DCON) ){
120
121                 switcho ){
122
123                 case NOT:
124                         ifhflag ) werror"constant argument to NOT" );
125                         ifl->in.op == FCON )
126                                 l->tn.lval = l->fpn.fval == 0.0;
127                         else
128                                 l->tn.lval = l->dpn.dval == 0.0;
129                         l->tn.rval = NONAME;
130                         l->in.op = ICON;
131                         l->fn.csiz = l->in.type = INT;
132                         l->fn.cdim = 0;
133                         return(l);
134                 case UNARY MINUS:
135                         ifl->in.op == FCON )
136                                 l->fpn.fval = -l->fpn.fval;
137                         else
138                                 l->dpn.dval = -l->dpn.dval;
139                         return(l);
140                         }
141                 }
142
143         else ifo==QUEST && l->in.op==ICON ) {
144                 l->in.op = FREE;
145                 r->in.op = FREE;
146                 ifl->tn.lval ){
147                         tfreer->in.right );
148                         returnr->in.left );
149                         }
150                 else {
151                         tfreer->in.left );
152                         returnr->in.right );
153                         }
154                 }
155
156         else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
157
158         else ifopty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
159
160                 switcho ){
161
162                 case ULT:
163                 case UGT:
164                 case ULE:
165                 case UGE:
166                 case LT:
167                 case GT:
168                 case LE:
169                 case GE:
170                 case EQ:
171                 case NE:
172                         ifl->in.type == ENUMTY && r->in.type == ENUMTY ){
173                                 p = blockolrINT0INT );
174                                 chkpunp );
175                                 p->in.op = FREE;
176                                 }
177
178                 case ANDAND:
179                 case OROR:
180                 case CBRANCH:
181
182                 ccwarn:
183                         ifhflag ) werror"constant in conditional context" );
184
185                 case PLUS:
186                 case MINUS:
187                 case MUL:
188                 case DIV:
189                 case MOD:
190                 case AND:
191                 case OR:
192                 case ER:
193                 case LS:
194                 case RS:
195                         ifconvallor ) ) {
196                                 r->in.op = FREE;
197                                 return(l);
198                                 }
199                         break;
200                         }
201                 }
202         else if (opty == BITYPE &&
203                 (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
204                 (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
205                         if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
206                                 extern int fpe_count;
207                                 extern jmp_buf gotfpe;
208
209                                 fpe_count = 0;
210                                 if (setjmp(gotfpe))
211                                         goto treatfpe;
212                                 if (l->in.op == ICON)
213                                         l->dpn.dval = l->tn.lval;
214                                 else if (l->in.op == FCON)
215                                         l->dpn.dval = l->fpn.fval;
216                                 if (r->in.op == ICON)
217                                         r->dpn.dval = r->tn.lval;
218                                 else if (r->in.op == FCON)
219                                         r->dpn.dval = r->fpn.fval;
220                                 switch (o) {
221
222                                 case PLUS:
223                                         l->dpn.dval += r->dpn.dval;
224                                         break;
225
226                                 case MINUS:
227                                         l->dpn.dval -= r->dpn.dval;
228                                         break;
229
230                                 case MUL:
231                                         l->dpn.dval *= r->dpn.dval;
232                                         break;
233
234                                 case DIV:
235                                         if (r->dpn.dval == 0)
236                                                 uerror("division by 0.");
237                                         else
238                                                 l->dpn.dval /= r->dpn.dval;
239                                         break;
240                                         }
241                         treatfpe:
242                                 if (fpe_count > 0) {
243                                         uerror("floating point exception in constant expression");
244                                         l->dpn.dval = 1.0/* Fairly harmless */
245                                         }
246                                 fpe_count = -1;
247                                 l->in.op = DCON;
248                                 l->in.type = l->fn.csiz = DOUBLE;
249                                 r->in.op = FREE;
250                                 return (l);
251                         }
252                 }
253
254         /* it's real; we must make a new node */
255
256         p = blockolrINT0INT );
257
258         actions = opact(p);
259 #ifndef BUG1
260         if (adebug)
261                 printact(pactions);
262 #endif
263
264         ifactions&LVAL ){ /* check left descendent */
265                 ifnotlval(p->in.left) ) {
266                         uerror"illegal lvalue operand of assignment operator" );
267                         }
268                 }
269
270         ifactions & NCVTR ){
271                 p->in.left = pconvertp->in.left );
272                 }
273         else if( !(actions & NCVT ) ){
274                 switchopty ){
275
276                 case BITYPE:
277                         p->in.right = pconvertp->in.right );
278                 case UTYPE:
279                         p->in.left = pconvertp->in.left );
280
281                         }
282                 }
283
ragge
1.7
284         if ((actions&PUN) && (o!=CAST||cflag))
ragge
1.1
285                 chkpun(p);
286
287         ifactions & (TYPL|TYPR) ){
288
289                 q = (actions&TYPL) ? p->in.left : p->in.right;
290
291                 p->in.type = q->in.type;
292                 p->fn.cdim = q->fn.cdim;
293                 p->fn.csiz = q->fn.csiz;
294                 }
295
296         ifactions & CVTL ) p = convertpCVTL );
297         ifactions & CVTR ) p = convertpCVTR );
298         ifactions & TYMATCH ) p = tymatch(p);
299         ifactions & PTMATCH ) p = ptmatch(p);
300
301         ifactions & OTHER ){
302                 l = p->in.left;
303                 r = p->in.right;
304
305                 switch(o){
306
307                 case NAME:
308                         sp = &stab[idname];
309                         ifsp->stype == UNDEF ){
310                                 uerror"%s undefined"sp->sname );
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                                 defidpSNULL );
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                         ifp->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                         ifi<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                         ifstab[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                                         ifddebug>1 ){
387                                                 printf("member %s==%s?\n",
388                                                         memnamtabnam);
389                                                 }
390 # endif
391                                         ifstab[memi].sflags & SNONUNIQ ){
392                                                 if (memnam != tabnam)
393                                                         goto next;
394                                                 r->tn.rval = i = memi;
395                                                 break;
396                                                 }
397                                         nextcontinue;
398                                         }
399                                 ifmemi < 0 )
400                                         uerror("illegal member use: %s",
401                                                 stab[i].sname);
402                                 }
403                         else {
ragge
1.2
404                                 int j;
ragge
1.1
405                                 ifl->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
406                                         ifstab[i].sflags & SNONUNIQ ){
407                                                 uerror"nonunique name demands struct/union or struct/union pointer" );
408                                                 }
409                                         else werror"struct/union or struct/union pointer required" );
410                                         }
411                                 else if( (j=l->fn.csiz+1)<0 ) cerror"undefined structure or union" );
412                                 else if( !chkstridimtab[j], DECREF(l->in.type) ) ){
413                                         werror"illegal member use: %s"stab[i].sname );
414                                         }
415                                 }
416
417                         p = strefp );
418                         break;
419
420                 case UNARY MUL:
421                         ifl->in.op == UNARY AND ){
422                                 p->in.op = l->in.op = FREE;
423                                 p = l->in.left;
424                                 }
425                         if( !ISPTR(l->in.type))uerror("illegal indirection");
426                         p->in.type = DECREF(l->in.type);
427                         p->fn.cdim = l->fn.cdim;
428                         p->fn.csiz = l->fn.csiz;
429                         break;
430
431                 case UNARY AND:
432                         switchl->in.op ){
433
434                         case UNARY MUL:
435                                 p->in.op = l->in.op = FREE;
436                                 p = l->in.left;
437                         case NAME:
438                                 p->in.type = INCREFl->in.type );
439                                 p->fn.cdim = l->fn.cdim;
440                                 p->fn.csiz = l->fn.csiz;
441                                 break;
442
443                         case COMOP:
444                                 lr = buildtreeUNARY ANDl->in.rightNIL );
445                                 p->in.op = l->in.op = FREE;
446                                 p = buildtreeCOMOPl->in.leftlr );
447                                 break;
448
449                         case QUEST:
450                                 lr = buildtreeUNARY ANDl->in.right->in.rightNIL );
451                                 ll = buildtreeUNARY ANDl->in.right->in.leftNIL );
452                                 p->in.op = l->in.op = l->in.right->in.op = FREE;
453                                 p = buildtreeQUESTl->in.leftbuildtreeCOLONlllr ) );
454                                 break;
455
456 # ifdef ADDROREG
457                         case OREG:
458                                 /* OREG was built in clocal()
459                                  * for an auto or formal parameter
460                                  * now its address is being taken
461                                  * local code must unwind it
462                                  * back to PLUS/MINUS REG ICON
463                                  * according to local conventions
464                                  */
465                                 p->in.op = FREE;
466                                 p = addroregl );
467                                 break;
468
469 # endif
470                         default:
471                                 uerror"unacceptable operand of &" );
472                                 break;
473                                 }
474                         break;
475
476                 case LS:
477                 case RS:
478                         ifl->in.type == CHAR || l->in.type == SHORT )
479                                 p->in.type = INT;
480                         else ifl->in.type == UCHAR || l->in.type == USHORT )
481                                 p->in.type = UNSIGNED;
482                         else
483                                 p->in.type = l->in.type;
484                 case ASG LS:
485                 case ASG RS:
486                         ifr->in.type != INT )
487                                 p->in.right = r = makety(rINT0INT );
488                         break;
489
490                 case RETURN:
491                 case ASSIGN:
492                 case CAST:
493                         /* structure assignment */
494                         /* take the addresses of the two sides; then make an
ragge
1.2
495                          * operator using STASG and
496                          * the addresses of left and right */
ragge
1.1
497
498                         {
ragge
1.2
499                                 TWORD t;
500                                 int ds;
ragge
1.1
501
502                                 ifl->fn.csiz != r->fn.csiz ) uerror"assignment of different structures" );
503
504                                 r = buildtreeUNARY ANDrNIL );
505                                 t = r->in.type;
506                                 d = r->fn.cdim;
507                                 s = r->fn.csiz;
508
509                                 l = blockSTASGlrtds );
510
511                                 ifo == RETURN ){
512                                         p->in.op = FREE;
513                                         p = l;
514                                         break;
515                                         }
516
517                                 p->in.op = UNARY MUL;
518                                 p->in.left = l;
519                                 p->in.right = NIL;
520                                 break;
521                                 }
522                 case COLON:
523                         /* structure colon */
524
525                         ifl->fn.csiz != r->fn.csiz ) uerror"type clash in conditional" );
526                         break;
527
528                 case CALL:
529                         p->in.right = r = fixargsp->in.right );
530                 case UNARY CALL:
531                         if( !ISPTR(l->in.type)) uerror("illegal function");
532                         p->in.type = DECREF(l->in.type);
533                         if( !ISFTN(p->in.type)) uerror("illegal function");
534                         p->in.type = DECREFp->in.type );
535                         p->fn.cdim = l->fn.cdim;
536                         p->fn.csiz = l->fn.csiz;
537                         ifl->in.op == UNARY AND && l->in.left->in.op == NAME &&
538                                 l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
539                                 ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
540                                 p->in.op += (FORTCALL-CALL);
541                                 }
542                         ifp->in.type == STRTY || p->in.type == UNIONTY ){
543                                 /* function returning structure */
544                                 /*  make function really return ptr to str., with * */
545
546                                 p->in.op += STCALL-CALL;
547                                 p->in.type = INCREFp->in.type );
548                                 p = buildtreeUNARY MULpNIL );
549
550                                 }
551                         break;
552
553                 default:
554                         cerror"other code %d"o );
555                         }
556
557                 }
558
559         ifactions & CVTO ) p = oconvert(p);
560         p = clocal(p);
561
562 # ifndef BUG1
563         ifbdebug ) fwalkpeprint0 );
564 # endif
565
566         return(p);
567
568         }
569
570 int fpe_count = -1;
571 jmp_buf gotfpe;
572
ragge
1.2
573 void fpe(int);
ragge
1.1
574 void
ragge
1.2
575 fpe(int a)
576 {
ragge
1.1
577         if (fpe_count < 0)
578                 cerror("floating point exception");
579         ++fpe_count;
580         longjmp(gotfpe1);
ragge
1.2
581 }
ragge
1.1
582
583 /*
584  * Rewrite arguments in a function call.
585  * Structure arguments are massaged, single
586  * precision floating point constants are
587  * cast to double (to eliminate convert code).
588  */
589 NODE *
590 fixargsp ) register NODE *p;  {
591         int o = p->in.op;
592
593         ifo == CM ){
594                 p->in.left = fixargsp->in.left );
595                 p->in.right = fixargsp->in.right );
596                 returnp );
597                 }
598
599         ifp->in.type == STRTY || p->in.type == UNIONTY ){
600                 p = blockSTARGpNILp->in.typep->fn.cdimp->fn.csiz );
601                 p->in.left = buildtreeUNARY ANDp->in.leftNIL );
602                 p = clocal(p);
603                 }
604         else ifo == FCON )
605                 p = makety(pDOUBLE00);
606         returnp );
ragge
1.2
607 }
ragge
1.1
608
ragge
1.2
609 /*
610  * is the MOS or MOU at stab[i] OK for strict reference by a ptr
611  * i has been checked to contain a MOS or MOU
612  * j is the index in dimtab of the members...
613  */
614 int
615 chkstr(int iint jTWORD type)
616 {
ragge
1.1
617         int kkk;
618
619         extern int ddebug;
620
621 # ifndef BUG1
622         ifddebug > 1 ) printf"chkstr( %s(%d), %d )\n"stab[i].snameij );
623 # endif
624         if( (k = j) < 0 ) uerror"undefined structure or union" );
625         else {
626                 for( ; (kk = dimtab[k] ) >= 0; ++k ){
627                         ifkk >= SYMTSZ ){
628                                 cerror"gummy structure" );
629                                 return(1);
630                                 }
631                         ifkk == i ) return1 );
632                         switchstab[kk].stype ){
633
634                         case STRTY:
635                         case UNIONTY:
636                                 iftype == STRTY ) continue;  /* no recursive looking for strs */
637                                 ifhflag && chkstridimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
638                                         ifstab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
639                                         werror(
640                                         "illegal member use: perhaps %s.%s?",
641                                         stab[kk].snamestab[i].sname );
642                                         return(1);
643                                         }
644                                 }
645                         }
646                 }
647         return0 );
ragge
1.2
648 }
ragge
1.1
649
ragge
1.2
650 /*
651  * apply the op o to the lval part of p; if binary, rhs is val
652  * works only on integer constants
653  */
654 int
655 conval(NODE *pint oNODE *q)
656 {
ragge
1.1
657         int iu;
658         CONSZ val;
659         TWORD utype;
660
661         val = q->tn.lval;
662         u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
663         ifu && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
664
665         ifp->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
666         ifq->tn.rval != NONAME && o!=PLUS ) return(0);
667         ifp->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
668
669         /* usual type conversions -- handle casts of constants */
670 #define ISLONG(t)       ((t) == LONG || (t) == ULONG)
ragge
1.6
671 #define ISLONGLONG(t)   ((t) == LONGLONG || (t) == ULONGLONG)
ragge
1.1
672         if (ISLONG(p->in.type) || ISLONG(q->in.type))
673                 utype = u ? ULONG : LONG;
ragge
1.6
674         else if (ISLONGLONG(p->in.type) || ISLONGLONG(q->in.type))
675                 utype = u ? ULONGLONG : LONGLONG;
ragge
1.1
676         else
677                 utype = u ? UNSIGNED : INT;
678         if( !ISPTR(p->in.type) && p->in.type != utype )
679                 p = makety(putype0, (int)utype);
680         ifq->in.type != utype )
681                 q = makety(qutype0, (int)utype);
682
683         switcho ){
684
685         case PLUS:
686                 p->tn.lval += val;
687                 ifp->tn.rval == NONAME ){
688                         p->tn.rval = q->tn.rval;
689                         p->in.type = q->in.type;
690                         }
691                 break;
692         case MINUS:
693                 p->tn.lval -= val;
694                 break;
695         case MUL:
696                 p->tn.lval *= val;
697                 break;
698         case DIV:
699                 ifval == 0 ) uerror"division by 0" );
700                 else if ( u ) p->tn.lval = (unsignedp->tn.lval / val;
701                 else p->tn.lval /= val;
702                 break;
703         case MOD:
704                 ifval == 0 ) uerror"division by 0" );
705                 else if ( u ) p->tn.lval = (unsignedp->tn.lval % val;
706                 else p->tn.lval %= val;
707                 break;
708         case AND:
709                 p->tn.lval &= val;
710                 break;
711         case OR:
712                 p->tn.lval |= val;
713                 break;
714         case ER:
715                 p->tn.lval ^= val;
716                 break;
717         case LS:
718                 i = val;
719                 p->tn.lval = p->tn.lval << i;
720                 break;
721         case RS:
722                 i = val;
723                 if ( u ) p->tn.lval = (unsignedp->tn.lval >> i;
724                 else p->tn.lval = p->tn.lval >> i;
725                 break;
726
727         case UNARY MINUS:
728                 p->tn.lval = - p->tn.lval;
729                 break;
730         case COMPL:
731                 p->tn.lval = ~p->tn.lval;
732                 break;
733         case NOT:
734                 p->tn.lval = !p->tn.lval;
735                 break;
736         case LT:
737                 p->tn.lval = p->tn.lval < val;
738                 break;
739         case LE:
740                 p->tn.lval = p->tn.lval <= val;
741                 break;
742         case GT:
743                 p->tn.lval = p->tn.lval > val;
744                 break;
745         case GE:
746                 p->tn.lval = p->tn.lval >= val;
747                 break;
748         case ULT:
749                 p->tn.lval = p->tn.lval < (unsignedval;
750                 break;
751         case ULE:
752                 p->tn.lval = p->tn.lval <= (unsignedval;
753                 break;
754         case UGT:
755                 p->tn.lval = p->tn.lval > (unsignedval;
756                 break;
757         case UGE:
758                 p->tn.lval = p->tn.lval >= (unsignedval;
759                 break;
760         case EQ:
761                 p->tn.lval = p->tn.lval == val;
762                 break;
763         case NE:
764                 p->tn.lval = p->tn.lval != val;
765                 break;
766         default:
767                 return(0);
768                 }
769         return(1);
770         }
771
ragge
1.7
772 /*
773  * Checks p for the existance of a pun.  This is called when the op of p
774  * is ASSIGN, RETURN, CAST, COLON, or relational.
775  * One case is when enumerations are used: this applies only to lint.
776  * In the other case, one operand is a pointer, the other integer type
777  * we check that this integer is in fact a constant zero...
778  * in the case of ASSIGN, any assignment of pointer to integer is illegal
779  * this falls out, because the LHS is never 0.
780  */
ragge
1.2
781 void
ragge
1.7
782 chkpun(NODE *p)
783 {
ragge
1.2
784         NODE *q;
785         int t1t2d1d2ref1ref2;
ragge
1.1
786
787         t1 = p->in.left->in.type;
788         t2 = p->in.right->in.type;
789
ragge
1.7
790         /* check for enumerations */
791         if (t1==ENUMTY || t2==ENUMTY) {
ragge
1.1
792                 /* rob pike says this is obnoxious...
793                 if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
794                         werror( "comparison of enums" ); */
ragge
1.7
795                 if (t1==ENUMTY && t2==ENUMTY) {
796                         if (p->in.left->fn.csiz!=p->in.right->fn.csiz)
797                                 werror("enumeration type clash, "
798                                     "operator %s"opst[p->in.op]);
ragge
1.1
799                         return;
800                 }
ragge
1.7
801                 if (t1 == ENUMTY)
802                         t1 = INT;
803                 if (t2 == ENUMTY)
804                         t2 = INT;
805         }
ragge
1.1
806
807         ref1 = ISPTR(t1) || ISARY(t1);
808         ref2 = ISPTR(t2) || ISARY(t2);
809
ragge
1.7
810         if (ref1 ^ ref2) {
811                 if (ref1)
812                         q = p->in.right;
813                 else
814                         q = p->in.left;
815                 if (q->in.op != ICON || q->tn.lval != 0)
816                         werror("illegal combination of pointer "
817                             "and integer, op %s"opst[p->in.op]);
818         } else if (ref1) {
819                 if (t1 == t2) {
820                         if (p->in.left->fn.csiz != p->in.right->fn.csiz) {
ragge
1.5
821                                 werror("illegal structure pointer combination");
ragge
1.1
822                                 return;
ragge
1.5
823                         }
ragge
1.1
824                         d1 = p->in.left->fn.cdim;
825                         d2 = p->in.right->fn.cdim;
ragge
1.7
826                         for (;;) {
827                                 if (ISARY(t1)) {
828                                         if (dimtab[d1] != dimtab[d2]) {
829                                                 werror("illegal array "
830                                                     "size combination");
ragge
1.1
831                                                 return;
ragge
1.5
832                                         }
ragge
1.1
833                                         ++d1;
834                                         ++d2;
ragge
1.5
835                                 } else
ragge
1.7
836                                         if (!ISPTR(t1))
ragge
1.5
837                                                 break;
ragge
1.1
838                                 t1 = DECREF(t1);
839                         }
ragge
1.7
840                 } else if (t1 != INCREF(UNDEF) && t2 != INCREF(UNDEF))
841                         werror("illegal pointer combination");
ragge
1.1
842         }
ragge
1.5
843 }
ragge
1.1
844
845 NODE *
846 strefp ) register NODE *p; {
847
848         TWORD t;
849         int dsdscalign;
850         OFFSZ off;
851         register struct symtab *q;
852
853         /* make p->x */
854         /* this is also used to reference automatic variables */
855
856         q = &stab[p->in.right->tn.rval];
857         p->in.right->in.op = FREE;
858         p->in.op = FREE;
859         p = pconvertp->in.left );
860
861         /* make p look like ptr to x */
862
863         if( !ISPTR(p->in.type)){
864                 p->in.type = PTR+UNIONTY;
865                 }
866
867         t = INCREFq->stype );
868         d = q->dimoff;
869         s = q->sizoff;
870
871         p = maketyptds );
872
873         /* compute the offset to be added */
874
875         off = q->offset;
876         dsc = q->sclass;
877
878         ifdsc & FIELD ) {  /* normalize offset */
879                 align = ALINT;
880                 s = INT;
881                 off = (off/align)*align;
882                 }
883         ifoff != 0 ) p = clocalblockPLUSpoffconofftds ), tds ) );
884
885         p = buildtreeUNARY MULpNIL );
886
887         /* if field, build field info */
888
889         ifdsc & FIELD ){
890                 p = blockFLDpNILq->stype0q->sizoff );
891                 p->tn.rval = PKFIELDdsc&FLDSIZq->offset%align );
892                 }
893
894         returnclocal(p) );
895         }
896
ragge
1.2
897 int
ragge
1.1
898 notlval(pregister NODE *p; {
899
900         /* return 0 if p an lvalue, 1 otherwise */
901
902         again:
903
904         switchp->in.op ){
905
906         case FLD:
907                 p = p->in.left;
908                 goto again;
909
910         case UNARY MUL:
911                 /* fix the &(a=b) bug, given that a and b are structures */
912                 ifp->in.left->in.op == STASG ) return1 );
913                 /* and the f().a bug, given that f returns a structure */
914                 ifp->in.left->in.op == UNARY STCALL ||
915                     p->in.left->in.op == STCALL ) return1 );
916         case NAME:
917         case OREG:
918                 ifISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
919         case REG:
920                 return(0);
921
922         default:
923                 return(1);
924
925                 }
926
927         }
928
929 NODE *
930 bconi ){ /* make a constant node with value i */
931         register NODE *p;
932
933         p = blockICONNILNILINT0INT );
934         p->tn.lval = i;
935         p->tn.rval = NONAME;
936         returnclocal(p) );
937         }
938
939 NODE *
940 bpsize(pregister NODE *p; {
941         returnoffconpsize(p), p->in.typep->fn.cdimp->fn.csiz ) );
942         }
943
944 OFFSZ
945 psizep ) NODE *p; {
946         /* p is a node of type pointer; psize returns the
947            size of the thing pointed to */
948
949         if( !ISPTR(p->in.type) ){
950                 uerror"pointer required");
951                 returnSZINT );
952                 }
953         /* note: no pointers to fields */
954         returntsizeDECREF(p->in.type), p->fn.cdimp->fn.csiz ) );
955         }
956
957 NODE *
958 convertpf )  register NODE *p; {
959         /*  convert an operand of p
960             f is either CVTL or CVTR
961             operand has type int, and is converted by the size of the other side
962             */
963
964         register NODE *q, *r;
965
966         q = (f==CVTL)?p->in.left:p->in.right;
967
968         r = blockPMCONV,
969                 qbpsize(f==CVTL?p->in.right:p->in.left), INT0INT );
970         r = clocal(r);
971         iff == CVTL )
972                 p->in.left = r;
973         else
974                 p->in.right = r;
975         return(p);
976
977         }
978
979 #ifndef econvert
ragge
1.2
980 void
ragge
1.1
981 econvertp ) register NODE *p; {
982
983         /* change enums to ints, or appropriate types */
984
985         register TWORD ty;
986
987         if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
ragge
1.6
988                 if (dimtab[p->fn.csiz] == SZCHAR)
989                         ty = CHAR;
990                 else if (dimtab[p->fn.csiz] == SZINT)
991                         ty = INT;
992                 else if (dimtab[p->fn.csiz] == SZSHORT)
993                         ty = SHORT;
994                 else if (dimtab[p->fn.csiz] == SZLONGLONG)
995                         ty = LONGLONG;
996                 else
997                         ty = LONG;
998                 ty = ctype(ty);
ragge
1.1
999                 p->fn.csiz = ty;
1000                 MODTYPE(p->in.type,ty);
ragge
1.6
1001                 if (p->in.op == ICON && ty != LONG && ty != LONGLONG)
1002                         p->in.type = p->fn.csiz = INT;
ragge
1.1
1003                 }
1004         }
1005 #endif
1006
1007 NODE *
1008 pconvertp ) register NODE *p; {
1009
1010         /* if p should be changed into a pointer, do so */
1011
1012         ifISARYp->in.type) ){
1013                 p->in.type = DECREFp->in.type );
1014                 ++p->fn.cdim;
1015                 returnbuildtreeUNARY ANDpNIL ) );
1016                 }
1017         ifISFTNp->in.type) )
1018                 returnbuildtreeUNARY ANDpNIL ) );
1019
1020         returnp );
1021         }
1022
1023 NODE *
1024 oconvert(pregister NODE *p; {
1025         /* convert the result itself: used for pointer and unsigned */
1026
1027         switch(p->in.op) {
1028
1029         case LE:
1030         case LT:
1031         case GE:
1032         case GT:
1033                 ifISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
1034         case EQ:
1035         case NE:
1036                 returnp );
1037
1038         case MINUS:
1039                 return(  clocalblockPVCONV,
1040                         pbpsize(p->in.left), INT0INT ) ) );
1041                 }
1042
1043         cerror"illegal oconvert: %d"p->in.op );
1044
1045         return(p);
1046         }
1047