Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20120322185140

Diff

Diff from 1.2 to:

Annotations

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

Annotated File View

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