Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20120101162054

Diff

Diff from 1.1 to:

Annotations

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

Annotated File View

ragge
1.1
1 /*      $Id: trees.c,v 1.1 2012/01/01 16:20:55 ragge Exp $      */
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 /*
30  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  *
36  * Redistributions of source code and documentation must retain the above
37  * copyright notice, this list of conditions and the following disclaimer.
38  * Redistributions in binary form must reproduce the above copyright
39  * notice, this list of conditionsand the following disclaimer in the
40  * documentation and/or other materials provided with the distribution.
41  * All advertising materials mentioning features or use of this software
42  * must display the following acknowledgement:
43  *      This product includes software developed or owned by Caldera
44  *      International, Inc.
45  * Neither the name of Caldera International, Inc. nor the names of other
46  * contributors may be used to endorse or promote products derived from
47  * this software without specific prior written permission.
48  *
49  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
50  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
51  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
54  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
58  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
60  * POSSIBILITY OF SUCH DAMAGE.
61  */
62 /*
63  * Some of the changes from 32V include:
64  * - Understand "void" as type.
65  * - Handle enums as ints everywhere.
66  * - Convert some C-specific ops into branches.
67  */
68
69 # include "pass1.h"
70 # include "pass2.h"
71
72 # include <stdarg.h>
73 # include <string.h>
74
75 static void chkpun(NODE *p);
76 static int opact(NODE *p);
77 static int moditype(TWORD);
78 static NODE *strargs(NODE *);
79 static void rmcops(NODE *p);
80 static NODE *tymatch(NODE *p);
81 void putjops(NODE *, void *);
82 static struct symtab *findmember(struct symtab *, char *);
83 int inftn/* currently between epilog/prolog */
84
85 static char *tnames[] = {
86         "undef",
87         "farg",
88         "char",
89         "unsigned char",
90         "short",
91         "unsigned short",
92         "int",
93         "unsigned int",
94         "long",
95         "unsigned long",
96         "long long",
97         "unsigned long long",
98         "float",
99         "double",
100         "long double",
101         "strty",
102         "unionty",
103         "enumty",
104         "moety",
105         "void",
106         "signed"/* pass1 */
107         "bool"/* pass1 */
108         "fimag"/* pass1 */
109         "dimag"/* pass1 */
110         "limag"/* pass1 */
111         "fcomplex"/* pass1 */
112         "dcomplex"/* pass1 */
113         "lcomplex"/* pass1 */
114         "enumty"/* pass1 */
115         "?""?"
116 };
117
118 /*      some special actions, used in finding the type of nodes */
119 # define NCVT 01
120 # define PUN 02
121 # define TYPL 04
122 # define TYPR 010
123 # define TYMATCH 040
124 # define LVAL 0100
125 # define CVTO 0200
126 # define CVTL 0400
127 # define CVTR 01000
128 # define PTMATCH 02000
129 # define OTHER 04000
130 # define NCVTR 010000
131 # define PROML 020000   /* promote left operand */
132
133 /* node conventions:
134
135         NAME:   rval>0 is stab index for external
136                 rval<0 is -inlabel number
137                 lval is offset in bits
138         ICON:   lval has the value
139                 rval has the STAB index, or - label number,
140                         if a name whose address is in the constant
141                 rval = NONAME means no name
142         REG:    rval is reg. identification cookie
143
144         */
145
146 int bdebug = 0;
147 extern int negrel[];
148
149 /* Have some defaults for most common targets */
150 #ifndef WORD_ADDRESSED
151 #define offcon(o,t,d,ap) xbcon((o/SZCHAR), NULL, INTPTR)
152 #define VBLOCK(p,b,t,d,a) buildtree(DIV, p, b)
153 #define MBLOCK(p,b,t,d,a) buildtree(MUL, p, b)
154 #else
155 #define VBLOCK(p,b,t,d,a) block(PVCONV, p, b, t, d, a)
156 #define MBLOCK(p,b,t,d,a) block(PMCONV, p, b, t, d, a)
157 #endif
158
159 NODE *
160 buildtree(int oNODE *lNODE *r)
161 {
162         NODE *p, *q;
163         int actions;
164         int optyn;
165         struct symtab *sp = NULL/* XXX gcc */
166         NODE *lr, *ll;
167
168 #ifdef PCC_DEBUG
169         if (bdebug) {
170                 printf("buildtree(%s, %p, %p)\n"copst(o), lr);
171                 if (lfwalk(leprint0);
172                 if (rfwalk(reprint0);
173         }
174 #endif
175         opty = coptype(o);
176
177         /* check for constants */
178
179         if (o == ANDAND || o == OROR || o == NOT) {
180                 if (l->n_op == FCON) {
181                         p = bcon(!FLOAT_ISZERO(l->n_dcon));
182                         nfree(l);
183                         l = p;
184                 }
185                 if (o != NOT && r->n_op == FCON) {
186                         p = bcon(!FLOAT_ISZERO(r->n_dcon));
187                         nfree(r);
188                         r = p;
189                 }
190         }
191
192         ifopty == UTYPE && l->n_op == ICON ){
193
194                 switcho ){
195
196                 case NOT:
197                 case UMINUS:
198                 case COMPL:
199                         ifconvallol ) ) return(l);
200                         break;
201                 }
202         } else if (o == NOT && l->n_op == FCON) {
203                 l = clocal(block(SCONVlNILINT00));
204         } else ifo == UMINUS && l->n_op == FCON ){
205                         l->n_dcon = FLOAT_NEG(l->n_dcon);
206                         return(l);
207
208         } else ifo==QUEST &&
209             (l->n_op==ICON || (l->n_op==NAME && ISARY(l->n_type)))) {
210                 CONSZ c = l->n_lval;
211                 if (l->n_op==NAME)
212                         c = 1/* will become constant later */
213                 nfree(l);
214                 if (c) {
215                         walkf(r->n_rightputjops0);
216                         tfree(r->n_right);
217                         l = r->n_left;
218                 } else {
219                         walkf(r->n_leftputjops0);
220                         tfree(r->n_left);
221                         l = r->n_right;
222                 }
223                 nfree(r);
224                 return(l);
225         } else ifopty == BITYPE && l->n_op == ICON && r->n_op == ICON ){
226
227                 switcho ){
228
229                 case PLUS:
230                 case MINUS:
231                 case MUL:
232                 case DIV:
233                 case MOD:
234                         /*
235                          * Do type propagation for simple types here.
236                          * The constant value is correct anyway.
237                          * Maybe this op shortcut should be removed?
238                          */
239                         if (l->n_sp == NULL && r->n_sp == NULL &&
240                             l->n_type < BTMASK && r->n_type < BTMASK) {
241                                 if (l->n_type > r->n_type)
242                                         r->n_type = l->n_type;
243                                 else
244                                         l->n_type = r->n_type;
245                         }
246                         /* FALLTHROUGH */
247                 case ULT:
248                 case UGT:
249                 case ULE:
250                 case UGE:
251                 case LT:
252                 case GT:
253                 case LE:
254                 case GE:
255                 case EQ:
256                 case NE:
257                 case ANDAND:
258                 case OROR:
259                 case AND:
260                 case OR:
261                 case ER:
262                 case LS:
263                 case RS:
264                         if (!ISPTR(l->n_type) && !ISPTR(r->n_type)) {
265                                 ifconvallor ) ) {
266                                         nfree(r);
267                                         return(l);
268                                 }
269                         }
270                         break;
271                 }
272         } else if (opty == BITYPE && (l->n_op == FCON || l->n_op == ICON) &&
273             (r->n_op == FCON || r->n_op == ICON) && (o == PLUS || o == MINUS ||
274             o == MUL || o == DIV || (o >= EQ && o <= GT) )) {
275                 TWORD t;
276 #ifndef CC_DIV_0
277                 if (o == DIV &&
278                     ((r->n_op == ICON && r->n_lval == 0) ||
279                      (r->n_op == FCON && r->n_dcon == 0.0)))
280                                 goto runtime/* HW dependent */
281 #endif
282                 if (l->n_op == ICON)
283                         l->n_dcon = FLOAT_CAST(l->n_lvall->n_type);
284                 if (r->n_op == ICON)
285                         r->n_dcon = FLOAT_CAST(r->n_lvalr->n_type);
286                 switch(o){
287                 case PLUS:
288                 case MINUS:
289                 case MUL:
290                 case DIV:
291                         switch (o) {
292                         case PLUS:
293                                 l->n_dcon = FLOAT_PLUS(l->n_dconr->n_dcon);
294                                 break;
295                         case MINUS:
296                                 l->n_dcon = FLOAT_MINUS(l->n_dconr->n_dcon);
297                                 break;
298                         case MUL:
299                                 l->n_dcon = FLOAT_MUL(l->n_dconr->n_dcon);
300                                 break;
301                         case DIV:
302                                 l->n_dcon = FLOAT_DIV(l->n_dconr->n_dcon);
303                                 break;
304                         }
305                         t = (l->n_type > r->n_type ? l->n_type : r->n_type);
306                         l->n_op = FCON;
307                         l->n_type = t;
308                         nfree(r);
309                         return(l);
310                 case EQ:
311                 case NE:
312                 case LE:
313                 case LT:
314                 case GE:
315                 case GT:
316                         switch (o) {
317                         case EQ:
318                                 n = FLOAT_EQ(l->n_dconr->n_dcon);
319                                 break;
320                         case NE:
321                                 n = FLOAT_NE(l->n_dconr->n_dcon);
322                                 break;
323                         case LE:
324                                 n = FLOAT_LE(l->n_dconr->n_dcon);
325                                 break;
326                         case LT:
327                                 n = FLOAT_LT(l->n_dconr->n_dcon);
328                                 break;
329                         case GE:
330                                 n = FLOAT_GE(l->n_dconr->n_dcon);
331                                 break;
332                         case GT:
333                                 n = FLOAT_GT(l->n_dconr->n_dcon);
334                                 break;
335                         default:
336                                 n = 0/* XXX flow analysis */
337                         }
338                         nfree(r);
339                         nfree(l);
340                         return bcon(n);
341                 }
342         }
343 #ifndef CC_DIV_0
344 runtime:
345 #endif
346         /* its real; we must make a new node */
347
348         p = block(olrINT00);
349
350         actions = opact(p);
351
352         if (actions & PROML)
353                 p->n_left = intprom(p->n_left);
354
355         if (actions & LVAL) { /* check left descendent */
356                 if (notlval(p->n_left)) {
357                         uerror("lvalue required");
358                         nfree(p);
359                         return l;
360 #ifdef notyet
361                 } else {
362                         if ((l->n_type > BTMASK && ISCON(l->n_qual)) ||
363                             (l->n_type <= BTMASK && ISCON(l->n_qual << TSHIFT)))
364                                 if (blevel > 0)
365                                         uerror("lvalue is declared const");
366 #endif
367                 }
368         }
369
370         ifactions & NCVTR ){
371                 p->n_left = pconvertp->n_left );
372                 }
373         else if( !(actions & NCVT ) ){
374                 switchopty ){
375
376                 case BITYPE:
377                         p->n_right = pconvertp->n_right );
378                 case UTYPE:
379                         p->n_left = pconvertp->n_left );
380
381                         }
382                 }
383
384         if ((actions&PUN) && (o!=CAST))
385                 chkpun(p);
386
387         ifactions & (TYPL|TYPR) ){
388
389                 q = (actions&TYPL) ? p->n_left : p->n_right;
390
391                 p->n_type = q->n_type;
392                 p->n_qual = q->n_qual;
393                 p->n_df = q->n_df;
394                 p->n_ap = q->n_ap;
395                 }
396
397         ifactions & CVTL ) p = convertpCVTL );
398         ifactions & CVTR ) p = convertpCVTR );
399         ifactions & TYMATCH ) p = tymatch(p);
400         ifactions & PTMATCH ) p = ptmatch(p);
401
402         ifactions & OTHER ){
403                 struct symtab *sp1;
404
405                 l = p->n_left;
406                 r = p->n_right;
407
408                 switch(o){
409
410                 case NAME:
411                         cerror("buildtree NAME");
412
413                 case STREF:
414                         /* p->x turned into *(p+offset) */
415                         /* rhs must be a name; check correctness */
416
417                         /* Find member symbol struct */
418                         if (l->n_type != PTR+STRTY && l->n_type != PTR+UNIONTY){
419                                 uerror("struct or union required");
420                                 break;
421                         }
422
423                         if ((sp1 = strmemb(l->n_ap)) == NULL) {
424                                 uerror("undefined struct or union");
425                                 break;
426                         }
427
428                         if ((sp = findmember(sp1r->n_name)) == NULL) {
429                                 uerror("member '%s' not declared"r->n_name);
430                                 break;
431                         }
432
433                         r->n_sp = sp;
434                         p = stref(p);
435                         break;
436
437                 case UMUL:
438                         if (l->n_op == ADDROF) {
439                                 nfree(p);
440                                 p = nfree(l);
441                         }
442                         if( !ISPTR(l->n_type))uerror("illegal indirection");
443                         p->n_type = DECREF(l->n_type);
444                         p->n_qual = DECREF(l->n_qual);
445                         p->n_df = l->n_df;
446                         p->n_ap = l->n_ap;
447                         break;
448
449                 case ADDROF:
450                         switchl->n_op ){
451
452                         case UMUL:
453                                 nfree(p);
454                                 p = nfree(l);
455                                 /* FALLTHROUGH */
456                         case TEMP:
457                         case NAME:
458                                 p->n_type = INCREF(l->n_type);
459                                 p->n_qual = INCQAL(l->n_qual);
460                                 p->n_df = l->n_df;
461                                 p->n_ap = l->n_ap;
462                                 break;
463
464                         case COMOP:
465                                 nfree(p);
466                                 lr = buildtree(ADDROFl->n_rightNIL);
467                                 p = buildtreeCOMOPl->n_leftlr );
468                                 nfree(l);
469                                 break;
470
471                         case QUEST:
472                                 lr = buildtreeADDROFl->n_right->n_rightNIL );
473                                 ll = buildtreeADDROFl->n_right->n_leftNIL );
474                                 nfree(p); nfree(l->n_right);
475                                 p = buildtreeQUESTl->n_leftbuildtreeCOLONlllr ) );
476                                 nfree(l);
477                                 break;
478
479                         default:
480                                 uerror("unacceptable operand of &: %d"l->n_op );
481                                 break;
482                                 }
483                         break;
484
485                 case LS:
486                 case RS/* must make type size at least int... */
487                         if (p->n_type == CHAR || p->n_type == SHORT) {
488                                 p->n_left = makety(lINT000);
489                         } else if (p->n_type == UCHAR || p->n_type == USHORT) {
490                                 p->n_left = makety(lUNSIGNED000);
491                         }
492                         l = p->n_left;
493                         p->n_type = l->n_type;
494                         p->n_qual = l->n_qual;
495                         p->n_df = l->n_df;
496                         p->n_ap = l->n_ap;
497
498                         /* FALLTHROUGH */
499                 case LSEQ:
500                 case RSEQ/* ...but not for assigned types */
501                         if(tsize(r->n_typer->n_dfr->n_ap) > SZINT)
502                                 p->n_right = makety(rINT000);
503                         break;
504
505                 case RETURN:
506                 case ASSIGN:
507                 case CAST:
508                         /* structure assignment */
509                         /* take the addresses of the two sides; then make an
510                          * operator using STASG and
511                          * the addresses of left and right */
512
513                         if (strmemb(l->n_ap) != strmemb(r->n_ap))
514                                 uerror("assignment of different structures");
515
516                         r = buildtree(ADDROFrNIL);
517
518                         l = block(STASGlrr->n_typer->n_dfr->n_ap);
519                         l = clocal(l);
520
521                         ifo == RETURN ){
522                                 nfree(p);
523                                 p = l;
524                                 break;
525                         }
526
527                         p->n_op = UMUL;
528                         p->n_left = l;
529                         p->n_right = NIL;
530                         break;
531
532                 case QUEST/* fixup types of : */
533                         if (r->n_left->n_type != p->n_type)
534                                 r->n_left = makety(r->n_leftp->n_type,
535                                     p->n_qualp->n_dfp->n_ap);
536                         if (r->n_right->n_type != p->n_type)
537                                 r->n_right = makety(r->n_rightp->n_type,
538                                     p->n_qualp->n_dfp->n_ap);
539                         break;
540
541                 case COLON:
542                         /* structure colon */
543
544                         if (strmemb(l->n_ap) != strmemb(r->n_ap))
545                                 uerror"type clash in conditional" );
546                         break;
547
548                 case CALL:
549                         p->n_right = r = strargs(p->n_right);
550                         p = funcode(p);
551                         /* FALLTHROUGH */
552                 case UCALL:
553                         if (!ISPTR(l->n_type))
554                                 uerror("illegal function");
555                         p->n_type = DECREF(l->n_type);
556                         if (!ISFTN(p->n_type))
557                                 uerror("illegal function");
558                         p->n_type = DECREF(p->n_type);
559                         p->n_df = l->n_df+1/* add one for prototypes */
560                         p->n_ap = l->n_ap;
561                         if (p->n_type == STRTY || p->n_type == UNIONTY) {
562                                 /* function returning structure */
563                                 /*  make function really return ptr to str., with * */
564
565                                 p->n_op += STCALL-CALL;
566                                 p->n_type = INCREF(p->n_type);
567                                 p = clocal(p); /* before recursing */
568                                 p = buildtree(UMULpNIL);
569
570                                 }
571                         break;
572
573                 default:
574                         cerror"other code %d"o );
575                         }
576
577                 }
578
579         /*
580          * Allow (void)0 casts.
581          * XXX - anything on the right side must be possible to cast.
582          * XXX - remove void types further on.
583          */
584         if (p->n_op == CAST && p->n_type == VOID &&
585             p->n_right->n_op == ICON)
586                 p->n_right->n_type = VOID;
587
588         if (actions & CVTO)
589                 p = oconvert(p);
590         p = clocal(p);
591
592 #ifdef PCC_DEBUG
593         if (bdebug) {
594                 printf("End of buildtree:\n");
595                 fwalk(peprint0);
596         }
597 #endif
598
599         return(p);
600
601         }
602
603 /* Find a member in a struct or union.  May be an unnamed member */
604 static struct symtab *
605 findmember(struct symtab *spchar *s)
606 {
607         struct symtab *sp2, *sp3;
608
609         for (; sp != NULLsp = sp->snext) {
610                 if (sp->sname[0] == '*') {
611                         /* unnamed member, recurse down */
612                         if ((sp2 = findmember(strmemb(sp->sap), s))) {
613                                 sp3 = tmpalloc(sizeof (struct symtab));
614                                 *sp3 = *sp2;
615                                 sp3->soffset += sp->soffset;
616                                 return sp3;
617                         }
618                 } else if (sp->sname == s)
619                         return sp;
620         }
621         return NULL;
622 }
623
624
625 /*
626  * Check if there will be a lost label destination inside of a ?:
627  * It cannot be reached so just print it out.
628  */
629 void
630 putjops(NODE *pvoid *arg)
631 {
632         if (p->n_op == COMOP && p->n_left->n_op == GOTO)
633                 plabel((int)p->n_left->n_left->n_lval+1);
634 }
635
636 /*
637  * Build a name node based on a symtab entry.
638  * broken out from buildtree().
639  */
640 NODE *
641 nametree(struct symtab *sp)
642 {
643         NODE *p;
644
645         p = block(NAMENILNILsp->stypesp->sdfsp->sap);
646         p->n_qual = sp->squal;
647         p->n_sp = sp;
648
649 #ifndef NO_C_BUILTINS
650         if (sp->sname[0] == '_' && strncmp(sp->sname"__builtin_"10) == 0)
651                 return p;  /* do not touch builtins here */
652         
653 #endif
654
655         if (sp->sflags & STNODE) {
656                 /* Generated for optimizer */
657                 p->n_op = TEMP;
658                 p->n_rval = sp->soffset;
659         }
660
661 #ifdef GCC_COMPAT
662         /* Get a label name */
663         if (sp->sflags == SLBLNAME) {
664                 p->n_type = VOID;
665         }
666 #endif
667         if (sp->stype == UNDEF) {
668                 uerror("%s undefined"sp->sname);
669                 /* make p look reasonable */
670                 p->n_type = INT;
671                 p->n_df = NULL;
672                 defid(pSNULL);
673         }
674         if (sp->sclass == MOE) {
675                 p->n_op = ICON;
676                 p->n_lval = sp->soffset;
677                 p->n_df = NULL;
678                 p->n_sp = NULL;
679         }
680         return clocal(p);
681 }
682
683 /*
684  * Cast a node to another type by inserting a cast.
685  * Just a nicer interface to buildtree.
686  * Returns the new tree.
687  */
688 NODE *
689 cast(NODE *pTWORD tTWORD u)
690 {
691         NODE *q;
692
693         q = block(NAMENILNILt00);
694         q->n_qual = u;
695         q = buildtree(CASTqp);
696         p = q->n_right;
697         nfree(q->n_left);
698         nfree(q);
699         return p;
700 }
701
702 /*
703  * Cast and complain if necessary by not inserining a cast.
704  */
705 NODE *
706 ccast(NODE *pTWORD tTWORD uunion dimfun *dfstruct attr *ap)
707 {
708         NODE *q;
709
710         /* let buildtree do typechecking (and casting) */ 
711         q = block(NAMENILNILtdfap);
712         p = buildtree(ASSIGNqp);
713         nfree(p->n_left);
714         q = optim(p->n_right);
715         nfree(p);
716         return q;
717 }
718
719 /*
720  * Do an actual cast of a constant (if possible).
721  * Routine assumes 2-complement (is there anything else today?)
722  * Returns 1 if handled, 0 otherwise.
723  */
724 int
725 concast(NODE *pTWORD t)
726 {
727         extern short sztable[];
728         CONSZ val;
729
730         if (p->n_op != ICON && p->n_op != FCON/* only constants */
731                 return 0;
732         if (p->n_op == ICON && p->n_sp != NULL) { /* no addresses */
733                 if (t == BOOL) {
734                         p->n_lval = 1p->n_type = BOOLp->n_sp = NULL;
735                         return 1;
736                 }
737                 return 0;
738         }
739         if ((p->n_type & TMASK) || (t & TMASK)) /* no cast of pointers */
740                 return 0;
741
742 //printf("concast till %d\n", t);
743 //fwalk(p, eprint, 0);
744
745 #define TYPMSK(y) ((((1LL << (y-1))-1) << 1) | 1)
746         if (p->n_op == ICON) {
747                 val = p->n_lval;
748
749                 if (t == BOOL) {
750                         if (val)
751                                 p->n_lval = 1;
752                 } else if (t <= ULONGLONG) {
753                         p->n_lval = val & TYPMSK(sztable[t]);
754                         if (!ISUNSIGNED(t)) {
755                                 if (val & (1LL << (sztable[t]-1)))
756                                         p->n_lval |= ~TYPMSK(sztable[t]);
757                         }
758                 } else if (t <= LDOUBLE) {
759                         p->n_op = FCON;
760                         p->n_dcon = FLOAT_CAST(valp->n_type);
761                 }
762         } else { /* p->n_op == FCON */
763                 if (t == BOOL) {
764                         p->n_op = ICON;
765                         p->n_lval = FLOAT_NE(p->n_dcon,0.0);
766                         p->n_sp = NULL;
767                 } else if (t <= ULONGLONG) {
768                         p->n_op = ICON;
769                         p->n_lval = ISUNSIGNED(t) ? /* XXX FIXME */
770                             ((U_CONSZ)p->n_dcon) : p->n_dcon;
771                         p->n_sp = NULL;
772                 } else {
773                         p->n_dcon = t == FLOAT ? (float)p->n_dcon :
774                             t == DOUBLE ? (double)p->n_dcon : p->n_dcon;
775                 }
776         }
777         p->n_type = t;
778 //fwalk(p, eprint, 0);
779         return 1;
780 }
781
782 /*
783  * Do a conditional branch.
784  */
785 void
786 cbranch(NODE *pNODE *q)
787 {
788         p = buildtree(CBRANCHpq);
789         if (p->n_left->n_op == ICON) {
790                 if (p->n_left->n_lval != 0) {
791                         branch((int)q->n_lval); /* branch always */
792                         reached = 0;
793                 }
794                 tfree(p);
795                 tfree(q);
796                 return;
797         }
798         ecomp(p);
799 }
800
801 NODE *
802 strargsp ) register NODE *p;  { /* rewrite structure flavored arguments */
803
804         ifp->n_op == CM ){
805                 p->n_left = strargsp->n_left );
806                 p->n_right = strargsp->n_right );
807                 returnp );
808                 }
809
810         ifp->n_type == STRTY || p->n_type == UNIONTY ){
811                 p = block(STARGpNILp->n_typep->n_dfp->n_ap);
812                 p->n_left = buildtreeADDROFp->n_leftNIL );
813                 p = clocal(p);
814                 }
815         returnp );
816 }
817
818 /*
819  * apply the op o to the lval part of p; if binary, rhs is val
820  */
821 int
822 conval(NODE *pint oNODE *q)
823 {
824         TWORD tl = p->n_typetr = q->n_typetd;
825         int iu;
826         CONSZ val;
827         U_CONSZ v1v2;
828
829         val = q->n_lval;
830
831         /* make both sides same type */
832         if (tl < BTMASK && tr < BTMASK) {
833                 td = tl > tr ? tl : tr;
834                 if (td < INT)
835                         td = INT;
836                 u = ISUNSIGNED(td);
837                 if (tl != td)
838                         p = makety(ptd000);
839                 if (tr != td)
840                         q = makety(qtd000);
841         } else
842                 u = ISUNSIGNED(tl) || ISUNSIGNED(tr);
843         ifu && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
844
845         if (p->n_sp != NULL && q->n_sp != NULL)
846                 return(0);
847         if (q->n_sp != NULL && o != PLUS)
848                 return(0);
849         if (p->n_sp != NULL && o != PLUS && o != MINUS)
850                 return(0);
851
852         v1 = p->n_lval;
853         v2 = q->n_lval;
854         if (v2 == 0 && (cdope(o) & DIVFLG))
855                 return 0/* leave division by zero to runtime */
856         switcho ){
857
858         case PLUS:
859                 p->n_lval += val;
860                 if (p->n_sp == NULL) {
861                         p->n_right = q->n_right;
862                         p->n_type = q->n_type;
863                 }
864                 break;
865         case MINUS:
866                 p->n_lval -= val;
867                 break;
868         case MUL:
869                 p->n_lval *= val;
870                 break;
871         case DIV:
872                 if (u) {
873                         v1 /= v2;
874                         p->n_lval = v1;
875                 } else
876                         p->n_lval /= val;
877                 break;
878         case MOD:
879                 if (u) {
880                         v1 %= v2;
881                         p->n_lval = v1;
882                 } else
883                         p->n_lval %= val;
884                 break;
885         case AND:
886                 p->n_lval &= val;
887                 break;
888         case OR:
889                 p->n_lval |= val;
890                 break;
891         case ER:
892                 p->n_lval ^= val;
893                 break;
894         case LS:
895                 i = (int)val;
896                 p->n_lval = p->n_lval << i;
897                 break;
898         case RS:
899                 i = (int)val;
900                 if (u) {
901                         v1 = v1 >> i;
902                         p->n_lval = v1;
903                 } else
904                         p->n_lval = p->n_lval >> i;
905                 break;
906
907         case UMINUS:
908                 p->n_lval = - p->n_lval;
909                 break;
910         case COMPL:
911                 p->n_lval = ~p->n_lval;
912                 break;
913         case NOT:
914                 p->n_lval = !p->n_lval;
915                 break;
916         case LT:
917                 p->n_lval = p->n_lval < val;
918                 break;
919         case LE:
920                 p->n_lval = p->n_lval <= val;
921                 break;
922         case GT:
923                 p->n_lval = p->n_lval > val;
924                 break;
925         case GE:
926                 p->n_lval = p->n_lval >= val;
927                 break;
928         case ULT:
929                 p->n_lval = v1 < v2;
930                 break;
931         case ULE:
932                 p->n_lval = v1 <= v2;
933                 break;
934         case UGT:
935                 p->n_lval = v1 > v2;
936                 break;
937         case UGE:
938                 p->n_lval = v1 >= v2;
939                 break;
940         case EQ:
941                 p->n_lval = p->n_lval == val;
942                 break;
943         case NE:
944                 p->n_lval = p->n_lval != val;
945                 break;
946         case ANDAND:
947                 p->n_lval = p->n_lval && val;
948                 break;
949         case OROR:
950                 p->n_lval = p->n_lval || val;
951                 break;
952         default:
953                 return(0);
954                 }
955         /* Do the best in making everything type correct after calc */
956         if (p->n_sp == NULL && q->n_sp == NULL)
957                 p->n_lval = valcast(p->n_lvalp->n_type);
958         return(1);
959         }
960
961 /*
962  * Ensure that v matches the type t; sign- or zero-extended
963  * as suitable to CONSZ.
964  * Only to be used for integer types.
965  */
966 CONSZ
967 valcast(CONSZ vTWORD t)
968 {
969         CONSZ r;
970         int sz;
971
972         if (t < CHAR || t > ULONGLONG)
973                 return v/* cannot cast */
974
975         if (t >= LONGLONG)
976                 return v/* already largest */
977
978 #define M(x)    ((((1ULL << ((x)-1)) - 1) << 1) + 1)
979 #define NOTM(x) (~M(x))
980 #define SBIT(x) (1ULL << ((x)-1))
981
982         sz = (int)tsize(tNULLNULL);
983         r = v & M(sz);
984         if (!ISUNSIGNED(t) && (SBIT(sz) & r))
985                 r = r | NOTM(sz);
986         return r;
987 }
988
989 /*
990  * Checks p for the existance of a pun.  This is called when the op of p
991  * is ASSIGN, RETURN, CAST, COLON, or relational.
992  * One case is when enumerations are used: this applies only to lint.
993  * In the other case, one operand is a pointer, the other integer type
994  * we check that this integer is in fact a constant zero...
995  * in the case of ASSIGN, any assignment of pointer to integer is illegal
996  * this falls out, because the LHS is never 0.
997  * XXX - check for COMOPs in assignment RHS?
998  */
999 void
1000 chkpun(NODE *p)
1001 {
1002         union dimfun *d1, *d2;
1003         NODE *q;
1004         int t1t2;
1005
1006         t1 = p->n_left->n_type;
1007         t2 = p->n_right->n_type;
1008
1009         switch (p->n_op) {
1010         case RETURN:
1011                 /* return of void allowed but nothing else */
1012                 if (t1 == VOID && t2 == VOID)
1013                         return;
1014                 if (t1 == VOID) {
1015                         werror("returning value from void function");
1016                         return;
1017                 }
1018                 if (t2 == VOID) {
1019                         uerror("using void value");
1020                         return;
1021                 }
1022         case COLON:
1023                 if (t1 == VOID && t2 == VOID)
1024                         return;
1025                 break;
1026         default:
1027                 if ((t1 == VOID && t2 != VOID) || (t1 != VOID && t2 == VOID)) {
1028                         uerror("value of void expression used");
1029                         return;
1030                 }
1031                 break;
1032         }
1033
1034         /* allow void pointer assignments in any direction */
1035         if (BTYPE(t1) == VOID && (t2 & TMASK))
1036                 return;
1037         if (BTYPE(t2) == VOID && (t1 & TMASK))
1038                 return;
1039
1040         /* boolean have special syntax */
1041         if (t1 == BOOL) {
1042                 if (!ISARY(t2)) /* Anything scalar */
1043                         return;
1044         }
1045
1046         if (ISPTR(t1) || ISARY(t1))
1047                 q = p->n_right;
1048         else
1049                 q = p->n_left;
1050
1051         if (!ISPTR(q->n_type) && !ISARY(q->n_type)) {
1052                 if (q->n_op != ICON || q->n_lval != 0)
1053                         werror("illegal combination of pointer and integer");
1054         } else {
1055                 if (t1 == t2) {
1056                         if (ISSOU(BTYPE(t1)) &&
1057                             !suemeq(p->n_left->n_app->n_right->n_ap))
1058                                 werror("illegal structure pointer combination");
1059                         return;
1060                 }
1061                 d1 = p->n_left->n_df;
1062                 d2 = p->n_right->n_df;
1063                 for (;;) {
1064                         if (ISARY(t1) || ISPTR(t1)) {
1065                                 if (!ISARY(t2) && !ISPTR(t2))
1066                                         break;
1067                                 if (ISARY(t1) && ISARY(t2) && d1->ddim != d2->ddim) {
1068                                         werror("illegal array size combination");
1069                                         return;
1070                                 }
1071                                 if (ISARY(t1))
1072                                         ++d1;
1073                                 if (ISARY(t2))
1074                                         ++d2;
1075                         } else if (ISFTN(t1)) {
1076                                 if (chkftn(d1->dfund2->dfun)) {
1077                                         werror("illegal function "
1078                                             "pointer combination");
1079                                         return;
1080                                 }
1081                                 ++d1;
1082                                 ++d2;
1083                         } else
1084                                 break;
1085                         t1 = DECREF(t1);
1086                         t2 = DECREF(t2);
1087                 }
1088                 if (DEUNSIGN(t1) != DEUNSIGN(t2))
1089                         warner(Wpointer_signNULL);
1090         }
1091 }
1092
1093 static NODE *
1094 offplus(NODE *pint offTWORD tTWORD qunion dimfun *dstruct attr *ap) {
1095         if (off != 0) {
1096                 p = block(PLUSpoffcon(offtdap), tdap);
1097                 p->n_qual = q;
1098                 p = optim(p);
1099         }
1100
1101         return buildtree(UMULpNIL);
1102 }
1103
1104 NODE *
1105 stref(NODE *p)
1106 {
1107         NODE *r;
1108         struct attr *ap, *xap, *yap;
1109         union dimfun *d;
1110         TWORD tq;
1111         int dsc;
1112         OFFSZ off;
1113         struct symtab *s;
1114
1115         /* make p->x */
1116         /* this is also used to reference automatic variables */
1117
1118         s = p->n_right->n_sp;
1119         nfree(p->n_right);
1120         r = nfree(p);
1121         xap = attr_find(r->n_apGCC_ATYP_PACKED);
1122
1123         p = pconvert(r);
1124
1125         /* make p look like ptr to x */
1126
1127         if (!ISPTR(p->n_type))
1128                 p->n_type = PTR+UNIONTY;
1129
1130         t = INCREF(s->stype);
1131         q = INCQAL(s->squal);
1132         d = s->sdf;
1133         ap = s->sap;
1134         if ((yap = attr_find(apGCC_ATYP_PACKED)) != NULL)
1135                 xap = yap;
1136         else if (xap != NULL)
1137                 ap = attr_add(apattr_dup(xap3));
1138         /* xap set if packed struct */
1139
1140         p = makety(ptqdap);
1141         if (ISFTN(s->stype)) {
1142                 /* direct class call */
1143                 p = block(NMLISTpnametree(s), INT00);
1144                 return p;
1145         }
1146
1147         /* compute the offset to be added */
1148
1149         off = s->soffset;
1150         dsc = s->sclass;
1151
1152         if (dsc & FIELD) {
1153                 TWORD ftyp = s->stype;
1154                 int fal = talign(ftypap);
1155                 off = (off/fal)*fal;
1156                 p = offplus(pofftqdap);
1157                 p = block(FLDpNILftyp0ap);
1158                 p->n_qual = q;
1159                 p->n_rval = PKFIELD(dsc&FLDSIZs->soffset%fal);
1160         } else {
1161                 p = offplus(pofftqdap);
1162 #ifndef CAN_UNALIGN
1163                 /* if target cannot handle unaligned addresses, fix here */
1164 #endif
1165         }
1166
1167         p = clocal(p);
1168         return p;
1169 }
1170
1171 int
1172 notlval(pregister NODE *p; {
1173
1174         /* return 0 if p an lvalue, 1 otherwise */
1175
1176         again:
1177
1178         switchp->n_op ){
1179
1180         case FLD:
1181                 p = p->n_left;
1182                 goto again;
1183
1184         case NAME:
1185         case OREG:
1186         case UMUL:
1187                 ifISARY(p->n_type) || ISFTN(p->n_type) ) return(1);
1188         case TEMP:
1189         case REG:
1190                 return(0);
1191
1192         default:
1193                 return(1);
1194
1195                 }
1196
1197         }
1198 /* make a constant node with value i */
1199 NODE *
1200 bcon(int i)
1201 {
1202         return xbcon(iNULLINT);
1203 }
1204
1205 NODE *
1206 xbcon(CONSZ valstruct symtab *spTWORD type)
1207 {
1208         NODE *p;
1209
1210         p = block(ICONNILNILtype00);
1211         p->n_lval = val;
1212         p->n_sp = sp;
1213         return clocal(p);
1214 }
1215
1216 NODE *
1217 bpsize(NODE *p)
1218 {
1219         int isdyn(struct symtab *sp);
1220         struct symtab s;
1221         NODE *q, *r;
1222         TWORD t;
1223         int sz;
1224
1225         s.stype = DECREF(p->n_type);
1226         s.sdf = p->n_df;
1227         if (isdyn(&s)) {
1228                 q = bcon(1);
1229                 for (t = s.stypet > BTMASKt = DECREF(t)) {
1230                         if (ISPTR(t))
1231                                 return buildtree(MULqbcon(SZPOINT(t)));
1232