Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20120422210740

Diff

Diff from 1.3 to:

Annotations

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

Annotated File View

plunky
1.3
1 /*      $Id: init.c,v 1.3 2012/04/22 21:07:41 plunky Exp $      */
ragge
1.1
2
3 /*
4  * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 /*
31  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  *
37  * Redistributions of source code and documentation must retain the above
38  * copyright notice, this list of conditions and the following disclaimer.
39  * Redistributions in binary form must reproduce the above copyright
40  * notice, this list of conditions and the following disclaimer in the
41  * documentation and/or other materials provided with the distribution.
42  * All advertising materials mentioning features or use of this software
43  * must display the following acknowledgement:
44  *      This product includes software developed or owned by Caldera
45  *      International, Inc.
46  * Neither the name of Caldera International, Inc. nor the names of other
47  * contributors may be used to endorse or promote products derived from
48  * this software without specific prior written permission.
49  *
50  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
51  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
52  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
55  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
59  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
60  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
61  * POSSIBILITY OF SUCH DAMAGE.
62  */
63
64 #include "pass1.h"
65 #include <string.h>
66
67 /*
68  * The following machine-dependent routines may be called during
69  * initialization:
70  * 
71  * zbits(OFFSZ, int)    - sets int bits of zero at position OFFSZ.
72  * infld(CONSZ off, int fsz, CONSZ val)
73  *                      - sets the bitfield val starting at off and size fsz.
74  * ninval(CONSZ off, int fsz, NODE *)
75  *                      - prints an integer constant which may have
76  *                        a label associated with it, located at off and
77  *                        size fsz.
78  *
79  * Initialization may be of different kind:
80  * - Initialization at compile-time, all values are constants and laid
81  *   out in memory. Static or extern variables outside functions.
82  * - Initialization at run-time, written to their values as code.
83  *
84  * Currently run-time-initialized variables are only initialized by using
85  * move instructions.  An optimization might be to detect that it is
86  * initialized with constants and therefore copied from readonly memory.
87  */
88
89 /*
90  * The base element(s) of an initialized variable is kept in a linked 
91  * list, allocated while initialized.
92  *
93  * When a scalar is found, entries are popped of the instk until it's
94  * possible to find an entry for a new scalar; then onstk() is called 
95  * to get the correct type and size of that scalar.
96  *
97  * If a right brace is found, pop the stack until a matching left brace
98  * were found while filling the elements with zeros.  This left brace is
99  * also marking where the current level is for designated initializations.
100  *
101  * Position entries are increased when traversing back down into the stack.
102  */
103
104 /*
105  * Good-to-know entries from symtab:
106  *      soffset - # of bits from beginning of this structure.
107  */
108
109 /*
110  * TO FIX:
111  * - Alignment of structs on like i386 char members.
112  */
113
114 /*
115  * Struct used in array initialisation.
116  */
117 static struct instk {
118         struct  instk *in_prev/* linked list */
119         struct  symtab *in_lnk/* member in structure initializations */
120         struct  symtab *in_sym/* symtab index */
121         union   dimfun *in_df;  /* dimenston of array */
122         TWORD   in_t;           /* type for this level */
123         int     in_n;           /* number of arrays seen so far */
124         int     in_fl;  /* flag which says if this level is controlled by {} */
125 } *pstkpbase;
126
127 int doing_initstatinit;
128 static struct symtab *csym;
129
130 #ifdef PCC_DEBUG
131 static void prtstk(struct instk *in);
132 #endif
133
134 /*
135  * Linked lists for initializations.
136  */
137 struct ilist {
138         struct ilist *next;
139         CONSZ off;      /* bit offset of this entry */
140         int fsz;        /* bit size of this entry */
141         NODE *n;        /* node containing this data info */
142 };
143
144 struct llist {
145         SLIST_ENTRY(llistnext;
146         CONSZ begsz;    /* bit offset of this entry */
147         struct ilist *il;
148 };
149 static SLIST_HEAD(llhllistlpole;
150 static CONSZ basesz;
151 static int numents/* # of array entries allocated */
152
153 static struct initctx {
154         struct initctx *prev;
155         struct instk *pstk;
156         struct symtab *psym;
157         struct llh lpole;
158         CONSZ basesz;
159         int numents;
160 } *inilnk;
161
162 static struct ilist *
163 getil(struct ilist *nextCONSZ bint szNODE *n)
164 {
165         struct ilist *il = tmpalloc(sizeof(struct ilist));
166
167         il->off = b;
168         il->fsz = sz;
169         il->n = n;
170         il->next = next;
171         return il;
172 }
173
174 /*
175  * Allocate a new struct defining a block of initializers appended to the
176  * end of the llist. Return that entry.
177  */
178 static struct llist *
179 getll(void)
180 {
181         struct llist *ll;
182
183         ll = tmpalloc(sizeof(struct llist));
184         ll->begsz = numents * basesz;
185         ll->il = NULL;
186         SLIST_INSERT_LAST(&lpolellnext);
187         numents++;
188         return ll;
189 }
190
191 /*
192  * Return structure containing off bitnumber.
193  * Allocate more entries, if needed.
194  */
195 static struct llist *
196 setll(OFFSZ off)
197 {
198         struct llist *ll = NULL;
199
200         /* Ensure that we have enough entries */
201         while (off >= basesz * numents)
202                  ll = getll();
203
204         if (ll != NULL && ll->begsz <= off && ll->begsz + basesz > off)
205                 return ll;
206
207         SLIST_FOREACH(ll, &lpolenext)
208                 if (ll->begsz <= off && ll->begsz + basesz > off)
209                         break;
210         return ll/* ``cannot fail'' */
211 }
212 char *astypnames[] = { 00"\t.byte""\t.byte""\t.short""\t.short",
213         "\t.word""\t.word""\t.long""\t.long""\t.quad""\t.quad",
214         "ERR""ERR""ERR",
215 };
216
217 void
218 inval(CONSZ offint fszNODE *p)
219 {
220         struct symtab *sp;
221         CONSZ val;
222         TWORD t;
223
224         if (p->n_op != ICON && p->n_op != FCON) {
225                 uerror("constant required");
226                 return;
227         }
228         if (p->n_type == BOOL) {
229                 if ((U_CONSZ)p->n_lval > 1)
230                         p->n_lval = 1;
231                 p->n_type = BOOL_TYPE;
232         }
233         if (ninval(offfszp))
234                 return/* dealt with in local.c */
235         t = p->n_type;
236         if (t > BTMASK)
237                 t = INTPTR;
238
239         val = (CONSZ)(p->n_lval & SZMASK(sztable[t]));
240         if (t <= ULONGLONG) {
241                 sp = p->n_sp;
242                 printf("%s ",astypnames[t]);
243                 if (val || sp == NULL)
244                         printf(CONFMTval);
245                 if (val && sp != NULL)
246                         printf("+");
247                 if (sp != NULL) {
248                         if ((sp->sclass == STATIC && sp->slevel > 0)) {
249                                 printf(LABFMTsp->soffset);
250                         } else
251                                 printf("%s"sp->soname ?
252                                     sp->soname : exname(sp->sname));
253                 }
254                 printf("\n");
255         } else
256                 cerror("inval: unhandled type %d", (int)t);
257 }
258
259 #ifndef MYBFINIT
260
261 static int inbits;
262 static CONSZ xinval;
263 /*
264  * Initialize a bitfield.
265  * XXX - use U_CONSZ?
266  */
267 void
268 infld(CONSZ offint fszCONSZ val)
269 {
270 #ifdef PCC_DEBUG
271         if (idebug)
272                 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
273                     offfszvalinbits);
274 #endif
275         val &= SZMASK(fsz);
276 #if TARGET_ENDIAN == TARGET_BE
277         while (fsz + inbits >= SZCHAR) {
278                 int shsz = SZCHAR-inbits;
279                 xinval = (xinval << shsz) | (val >> (fsz - shsz));
280                 printf("%s " CONFMT "\n",
281                     astypnames[CHAR], xinval & SZMASK(SZCHAR));
282                 fsz -= shsz;
283                 val &= SZMASK(fsz);
284                 xinval = inbits = 0;
285         }
286         if (fsz) {
287                 xinval = (xinval << fsz) | val;
288                 inbits += fsz;
289         }
290 #else
291         while (fsz + inbits >= SZCHAR) {
292                 int shsz = SZCHAR-inbits;
293                 xinval |= (val << inbits);
294                 printf("%s " CONFMT "\n",
295                     astypnames[CHAR], xinval & SZMASK(SZCHAR));
296                 fsz -= shsz;
297                 val >>= shsz;
298                 xinval = inbits = 0;
299         }
300         if (fsz) {
301                 xinval |= (val << inbits);
302                 inbits += fsz;
303         }
304 #endif
305 }
306
307 char *asspace = "\t.space";
308
309 /*
310  * set fsz bits in sequence to zero.
311  */
312 void
313 zbits(OFFSZ offint fsz)
314 {
315         int m;
316
317 #ifdef PCC_DEBUG
318         if (idebug)
319                 printf("zbits off %lld, fsz %d inbits %d\n"offfszinbits);
320 #endif
321 #if TARGET_ENDIAN == TARGET_BE
322         if ((m = (inbits % SZCHAR))) {
323                 m = SZCHAR - m;
324                 if (fsz < m) {
325                         inbits += fsz;
326                         xinval <<= fsz;
327                         return;
328                 } else {
329                         fsz -= m;
330                         xinval <<= m;
331                         printf("%s " CONFMT "\n"
332                             astypnames[CHAR], xinval & SZMASK(SZCHAR));
333                         xinval = inbits = 0;
334                 }
335         }
336 #else
337         if ((m = (inbits % SZCHAR))) {
338                 m = SZCHAR - m;
339                 if (fsz < m) {
340                         inbits += fsz;
341                         return;
342                 } else {
343                         fsz -= m;
344                         printf("%s " CONFMT "\n"
345                             astypnames[CHAR], xinval & SZMASK(SZCHAR));
346                         xinval = inbits = 0;
347                 }
348         }
349 #endif
350         if (fsz >= SZCHAR) {
351                 printf("%s %d\n"asspacefsz/SZCHAR);
352                 fsz -= (fsz/SZCHAR) * SZCHAR;
353         }
354         if (fsz) {
355                 xinval = 0;
356                 inbits = fsz;
357         }
358 }
359 #endif
360
361 /*
362  * beginning of initialization; allocate space to store initialized data.
363  * remember storage class for writeout in endinit().
364  * p is the newly declarated type.
365  */
366 void
367 beginit(struct symtab *sp)
368 {
369         struct initctx *ict;
370         struct instk *is = &pbase;
371
372 #ifdef PCC_DEBUG
373         if (idebug)
374                 printf("beginit(%p), sclass %s\n"spscnames(sp->sclass));
375 #endif
376
377         if (pstk) {
378 #ifdef PCC_DEBUG
379                 if (idebug)
380                         printf("beginit: saving ctx pstk %p\n"pstk);
381 #endif
382                 /* save old context */
383                 ict = tmpalloc(sizeof(struct initctx));
384                 ict->prev = inilnk;
385                 inilnk = ict;
386                 ict->pstk = pstk;
387                 ict->psym = csym;
388                 ict->lpole = lpole;
389                 ict->basesz = basesz;
390                 ict->numents = numents;
391                 is = tmpalloc(sizeof(struct instk));
392         }
393         csym = sp;
394
395         numents = 0/* no entries in array list */
396         if (ISARY(sp->stype)) {
397                 basesz = tsize(DECREF(sp->stype), sp->sdf+1sp->sap);
398                 if (basesz == 0) {
399                         uerror("array has incomplete type");
400                         basesz = SZINT;
401                 }
402         } else
403                 basesz = tsize(sp->stypesp->sdfsp->sap);
404         SLIST_INIT(&lpole);
405
406         /* first element */
407         if (ISSOU(sp->stype)) {
408                 is->in_lnk = strmemb(sp->sap);
409         } else
410                 is->in_lnk = NULL;
411         is->in_n = 0;
412         is->in_t = sp->stype;
413         is->in_sym = sp;
414         is->in_df = sp->sdf;
415         is->in_fl = 0;
416         is->in_prev = NULL;
417         pstk = is;
418         doing_init++;
419         if (sp->sclass == STATIC || sp->sclass == EXTDEF)
420                 statinit++;
421 }
422
423 /*
424  * Push a new entry on the initializer stack.
425  * The new entry will be "decremented" to the new sub-type of the previous
426  * entry when called.
427  * Popping of entries is done elsewhere.
428  */
429 static void
430 stkpush(void)
431 {
432         struct instk *is;
433         struct symtab *sq, *sp;
434         TWORD t;
435
436         if (pstk == NULL) {
437                 sp = csym;
438                 t = 0;
439         } else {
440                 t = pstk->in_t;
441                 sp = pstk->in_sym;
442         }
443
444 #ifdef PCC_DEBUG
445         if (idebug) {
446                 printf("stkpush: '%s' %s "sp->snamescnames(sp->sclass));
447                 tprint(stdoutt0);
448         }
449 #endif
450
451         /*
452          * Figure out what the next initializer will be, and push it on 
453          * the stack.  If this is an array, just decrement type, if it
454          * is a struct or union, extract the next element.
455          */
456         is = tmpalloc(sizeof(struct instk));
457         is->in_fl = 0;
458         is->in_n = 0;
459         if (pstk == NULL) {
460                 /* stack empty */
461                 is->in_lnk = ISSOU(sp->stype) ? strmemb(sp->sap) : NULL;
462                 is->in_t = sp->stype;
463                 is->in_sym = sp;
464                 is->in_df = sp->sdf;
465         } else if (ISSOU(t)) {
466                 sq = pstk->in_lnk;
467                 if (sq == NULL) {
468                         uerror("excess of initializing elements");
469                 } else {
470                         is->in_lnk = ISSOU(sq->stype) ? strmemb(sq->sap) : NULL;
471                         is->in_t = sq->stype;
472                         is->in_sym = sq;
473                         is->in_df = sq->sdf;
474                 }
475         } else if (ISARY(t)) {
476                 is->in_lnk = ISSOU(DECREF(t)) ? strmemb(pstk->in_sym->sap) : 0;
477                 is->in_t = DECREF(t);
478                 is->in_sym = sp;
479                 if (pstk->in_df->ddim != NOOFFSET && pstk->in_df->ddim &&
480                     pstk->in_n >= pstk->in_df->ddim) {
481                         werror("excess of initializing elements");
482                         pstk->in_n--;
483                 }
484                 is->in_df = pstk->in_df+1;
485         } else
486                 uerror("too many left braces");
487         is->in_prev = pstk;
488         pstk = is;
489
490 #ifdef PCC_DEBUG
491         if (idebug) {
492                 printf(" newtype ");
493                 tprint(stdoutis->in_t0);
494                 printf("\n");
495         }
496 #endif
497 }
498
499 /*
500  * pop down to either next level that can handle a new initializer or
501  * to the next braced level.
502  */
503 static void
504 stkpop(void)
505 {
506 #ifdef PCC_DEBUG
507         if (idebug)
508                 printf("stkpop\n");
509 #endif
510         for (; pstkpstk = pstk->in_prev) {
511                 if (pstk->in_t == STRTY && pstk->in_lnk != NULL) {
512                         pstk->in_lnk = pstk->in_lnk->snext;
513                         if (pstk->in_lnk != NULL)
514                                 break;
515                 }
516                 if (ISSOU(pstk->in_t) && pstk->in_fl)
517                         break/* need } */
518                 if (ISARY(pstk->in_t)) {
519                         pstk->in_n++;
520                         if (pstk->in_fl)
521                                 break;
522                         if (pstk->in_df->ddim == NOOFFSET ||
523                             pstk->in_n < pstk->in_df->ddim)
524                                 break/* ger more elements */
525                 }
526         }
527 #ifdef PCC_DEBUG
528         if (idebug > 1)
529                 prtstk(pstk);
530 #endif
531 }
532
533 /*
534  * Count how many elements an array may consist of.
535  */
536 static int
537 acalc(struct instk *isint n)
538 {
539         if (is == NULL || !ISARY(is->in_t))
540                 return 0;
541         return acalc(is->in_prevn * is->in_df->ddim) + n * is->in_n;
542 }
543
544 /*
545  * Find current bit offset of the top element on the stack from
546  * the beginning of the aggregate.
547  */
548 static CONSZ
549 findoff(void)
550 {
551         struct instk *is;
552         OFFSZ off;
553
554 #ifdef PCC_DEBUG
555         if (ISARY(pstk->in_t))
556                 cerror("findoff on bad type %x"pstk->in_t);
557 #endif
558
559         /*
560          * Offset calculations. If:
561          * - previous type is STRTY, soffset has in-struct offset.
562          * - this type is ARY, offset is ninit*stsize.
563          */
564         for (off = 0is = pstkisis = is->in_prev) {
565                 if (is->in_prev && is->in_prev->in_t == STRTY)
566                         off += is->in_sym->soffset;
567                 if (ISARY(is->in_t)) {
568                         /* suesize is the basic type, so adjust */
569                         TWORD t = is->in_t;
570                         OFFSZ o;
571                         while (ISARY(t))
572                                 t = DECREF(t);
573                         if (ISPTR(t)) {
574                                 o = SZPOINT(t); /* XXX use tsize() */
575                         } else {
576                                 o = tsize(tis->in_sym->sdfis->in_sym->sap);
577                         }
578                         off += o * acalc(is1);
579                         while (is->in_prev && ISARY(is->in_prev->in_t)) {
580                                 if (is->in_prev->in_prev &&
581                                     is->in_prev->in_prev->in_t == STRTY)
582                                         off += is->in_sym->soffset;
583                                 is = is->in_prev;
584                         }
585                 }
586         }
587 #ifdef PCC_DEBUG
588         if (idebug>1) {
589                 printf("findoff: off %lld\n"off);
590                 prtstk(pstk);
591         }
592 #endif
593         return off;
594 }
595
596 /*
597  * Insert the node p with size fsz at position off.
598  * Bit fields are already dealt with, so a node of correct type
599  * with correct alignment and correct bit offset is given.
600  */
601 static void
602 nsetval(CONSZ offint fszNODE *p)
603 {
604         struct llist *ll;
605         struct ilist *il;
606
607         if (idebug>1)
608                 printf("setval: off %lld fsz %d p %p\n"offfszp);
609
610         if (fsz == 0)
611                 return;
612
613         ll = setll(off);
614         off -= ll->begsz;
615         if (ll->il == NULL) {
616                 ll->il = getil(NULLofffszp);
617         } else {
618                 il = ll->il;
619                 if (il->off > off) {
620                         ll->il = getil(ll->ilofffszp);
621                 } else {
622                         for (il = ll->ilil->nextil = il->next)
623                                 if (il->off <= off && il->next->off > off)
624                                         break;
625                         if (il->off == off) {
626                                 /* replace */
627                                 nfree(il->n);
628                                 il->n = p;
629                         } else
630                                 il->next = getil(il->nextofffszp);
631                 }
632         }
633 }
634
635 /*
636  * take care of generating a value for the initializer p
637  * inoff has the current offset (last bit written)
638  * in the current word being generated
639  * Returns the offset.
640  */
641 CONSZ
642 scalinit(NODE *p)
643 {
644         CONSZ woff;
645         NODE *q;
646         int fsz;
647
648 #ifdef PCC_DEBUG
649         if (idebug > 2) {
650                 printf("scalinit(%p)\n"p);
651                 fwalk(peprint0);
652                 prtstk(pstk);
653         }
654 #endif
655
656         if (nerrors)
657                 return 0;
658
659         p = optim(p);
660
661 #ifdef notdef /* leave to the target to decide if useable */
662         if (csym->sclass != AUTO && p->n_op != ICON &&
663             p->n_op != FCON && p->n_op != NAME)
664                 cerror("scalinit not leaf");
665 #endif
666
667         /* Out of elements? */
668         if (pstk == NULL) {
669                 uerror("excess of initializing elements");
670                 return 0;
671         }
672
673         /*
674          * Get to the simple type if needed.
675          */
676         while (ISSOU(pstk->in_t) || ISARY(pstk->in_t)) {
677                 stkpush();
678                 /* If we are doing auto struct init */
679                 if (ISSOU(pstk->in_t) && ISSOU(p->n_type) &&
680                     suemeq(pstk->in_sym->sapp->n_ap))
681                         break;
682         }
683
684         if (ISSOU(pstk->in_t) == 0) {
685                 /* let buildtree do typechecking (and casting) */
686                 q = block(NAMENIL,NILpstk->in_tpstk->in_df,
687                     pstk->in_sym->sap);
688                 p = buildtree(ASSIGNqp);
689                 nfree(p->n_left);
690                 q = p->n_right;
691                 nfree(p);
692         } else
693                 q = p;
694 #ifndef WORD_ADDRESSED
695         if (csym->sclass != AUTO)
696                 q = rmpconv(optim(rmpconv(q)));
697 #endif
698         q = optim(q);
699
700         woff = findoff();
701
702         /* bitfield sizes are special */
703         if (pstk->in_sym->sclass & FIELD)
704                 fsz = -(pstk->in_sym->sclass & FLDSIZ);
705         else
706                 fsz = (int)tsize(pstk->in_tpstk->in_sym->sdf,
707                     pstk->in_sym->sap);
708
709         nsetval(wofffszq);
710
711         stkpop();
712 #ifdef PCC_DEBUG
713         if (idebug > 2) {
714                 printf("scalinit e(%p)\n"q);
715         }
716 #endif
717         return woff;
718 }
719
720 /*
721  * Generate code to insert a value into a bitfield.
722  */
723 static void
724 insbf(OFFSZ offint fszint val)
725 {
726         struct symtab sym;
727         NODE *p, *r;
728         TWORD typ;
729
730 #ifdef PCC_DEBUG
731         if (idebug > 1)
732                 printf("insbf: off %lld fsz %d val %d\n"offfszval);
733 #endif
734
735         if (fsz == 0)
736                 return;
737
738         /* small opt: do char instead of bf asg */
739         if ((off & (ALCHAR-1)) == 0 && fsz == SZCHAR)
740                 typ = CHAR;
741         else
742                 typ = INT;
743         /* Fake a struct reference */
744         p = buildtree(ADDROFnametree(csym), NIL);
745         sym.stype = typ;
746         sym.squal = 0;
747         sym.sdf = 0;
748         sym.sap = NULL;
749         sym.soffset = (int)off;
750         sym.sclass = (char)(typ == INT ? FIELD | fsz : MOU);
751         r = xbcon(0, &symtyp);
752         p = block(STREFprINT00);
753         ecomp(buildtree(ASSIGNstref(p), bcon(val)));
754 }
755
756 /*
757  * Clear a bitfield, starting at off and size fsz.
758  */
759 static void
760 clearbf(OFFSZ offOFFSZ fsz)
761 {
762         /* Pad up to the next even initializer */
763         if ((off & (ALCHAR-1)) || (fsz < SZCHAR)) {
764                 int ba = (int)(((off + (SZCHAR-1)) & ~(SZCHAR-1)) - off);
765                 if (ba > fsz)
766                         ba = (int)fsz;
767                 insbf(offba0);
768                 off += ba;
769                 fsz -= ba;
770         }
771         while (fsz >= SZCHAR) {
772                 insbf(offSZCHAR0);
773                 off += SZCHAR;
774                 fsz -= SZCHAR;
775         }
776         if (fsz)
777                 insbf(offfsz0);
778 }
779
780 /*
781  * final step of initialization.
782  * print out init nodes and generate copy code (if needed).
783  */
784 void
785 endinit(int seg)
786 {
787         struct llist *ll;
788         struct ilist *il;
789         int fsz;
790         OFFSZ lastofftbit;
791
792 #ifdef PCC_DEBUG
793         if (idebug)
794                 printf("endinit()\n");
795 #endif
796
797         /* Calculate total block size */
798         if (ISARY(csym->stype) && csym->sdf->ddim == NOOFFSET) {
799                 tbit = numents*basesz/* open-ended arrays */
800                 csym->sdf->ddim = numents;
801                 if (csym->sclass == AUTO) { /* Get stack space */
802                         csym->soffset = NOOFFSET;
803                         oalloc(csym, &autooff);
804                 }
805         } else
806                 tbit = tsize(csym->stypecsym->sdfcsym->sap);
807
808         /* Setup symbols */
809         if (csym->sclass != AUTO) {
810                 locctr(seg ? UDATA : DATAcsym);
811                 defloc(csym);
812         }
813
814         /* Traverse all entries and print'em out */
815         lastoff = 0;
816         SLIST_FOREACH(ll, &lpolenext) {
817                 for (il = ll->ililil = il->next) {
818 #ifdef PCC_DEBUG
819                         if (idebug > 1) {
820                                 printf("off %lld size %d val %lld type ",
821                                     ll->begsz+il->offil->fszil->n->n_lval);
822                                 tprint(stdoutil->n->n_type0);
823                                 printf("\n");
824                         }
825 #endif
826                         fsz = il->fsz;
827                         if (csym->sclass == AUTO) {
828                                 struct symtab sym;
829                                 NODE *p, *r, *n;
830
831                                 if (ll->begsz + il->off > lastoff)
832                                         clearbf(lastoff,
833                                             (ll->begsz + il->off) - lastoff);
834
835                                 /* Fake a struct reference */
836                                 p = buildtree(ADDROFnametree(csym), NIL);
837                                 n = il->n;
838                                 sym.stype = n->n_type;
839                                 sym.squal = n->n_qual;
840                                 sym.sdf = n->n_df;
841                                 sym.sap = n->n_ap;
842                                 sym.soffset = (int)(ll->begsz + il->off);
843                                 sym.sclass = (char)(fsz < 0 ? FIELD | -fsz : 0);
844                                 r = xbcon(0, &symINT);
845                                 p = block(STREFprINT00);
846                                 ecomp(buildtree(ASSIGNstref(p), il->n));
847                                 if (fsz < 0)
848                                         fsz = -fsz;
849
850                         } else {
851                                 if (ll->begsz + il->off > lastoff)
852                                         zbits(lastoff,
853                                             (ll->begsz + il->off) - lastoff);
854                                 if (fsz < 0) {
855                                         fsz = -fsz;
856                                         infld(il->offfszil->n->n_lval);
857                                 } else
858                                         inval(il->offfszil->n);
859                                 tfree(il->n);
860                         }
861                         lastoff = ll->begsz + il->off + fsz;
862                 }
863         }
864         if (csym->sclass == AUTO) {
865                 clearbf(lastofftbit-lastoff);
866         } else
867                 zbits(lastofftbit-lastoff);
868         
869         doing_init--;
870         if (csym->sclass == STATIC || csym->sclass == EXTDEF)
871                 statinit--;
872         endictx();
873 }
874
875 void
876 endictx(void)
877 {
878         struct initctx *ict = inilnk;
879
880         if (ict == NULL)
881                 return;
882
883         pstk = ict->pstk;
884         csym = ict->psym;
885         lpole = ict->lpole;
886         basesz = ict->basesz;
887         numents = ict->numents;
888         inilnk = inilnk->prev;
889 #ifdef PCC_DEBUG
890         if (idebug)
891                 printf("endinit: restoring ctx pstk %p\n"pstk);
892 #endif
893 }
894
895 /*
896  * process an initializer's left brace
897  */
898 void
plunky
1.3
899 ilbrace(void)
ragge
1.1
900 {
901 #ifdef PCC_DEBUG
902         if (idebug)
903                 printf("ilbrace()\n");
904 #endif
905
906         if (pstk == NULL)
907                 return;
908
909         stkpush();
910         pstk->in_fl = 1/* mark lbrace */
911 #ifdef PCC_DEBUG
912         if (idebug > 1)
913                 prtstk(pstk);
914 #endif
915 }
916
917 /*
918  * called when a '}' is seen
919  */
920 void
plunky
1.3
921 irbrace(void)
ragge
1.1
922 {
923 #ifdef PCC_DEBUG
924         if (idebug)
925                 printf("irbrace()\n");
926         if (idebug > 2)
927                 prtstk(pstk);
928 #endif
929
930         if (pstk == NULL)
931                 return;
932
933         /* Got right brace, search for corresponding in the stack */
934         for (; pstk->in_prev != NULLpstk = pstk->in_prev) {
935                 if(!pstk->in_fl)
936                         continue;
937
938                 /* we have one now */
939
940                 pstk->in_fl = 0;  /* cancel { */
941                 if (ISARY(pstk->in_t))
942                         pstk->in_n = pstk->in_df->ddim;
943                 else if (pstk->in_t == STRTY) {
944                         while (pstk->in_lnk != NULL &&
945                             pstk->in_lnk->snext != NULL)
946                                 pstk->in_lnk = pstk->in_lnk->snext;
947                 }
948                 stkpop();
949                 return;
950         }
951 }
952
953 /*
954  * Create a new init stack based on given elements.
955  */
956 static void
957 mkstack(NODE *p)
958 {
959
960 #ifdef PCC_DEBUG
961         if (idebug) {
962                 printf("mkstack: %p\n"p);
963                 if (idebug > 1 && p)
964                         fwalk(peprint0);
965         }
966 #endif
967
968         if (p == NULL)
969                 return;
970         mkstack(p->n_left);
971
972         switch (p->n_op) {
973         case LB/* Array index */
974                 if (p->n_right->n_op != ICON)
975                         cerror("mkstack");
976                 if (!ISARY(pstk->in_t))
977                         uerror("array indexing non-array");
978                 pstk->in_n = (int)p->n_right->n_lval;
979                 nfree(p->n_right);
980                 break;
981
982         case NAME:
983                 if (pstk->in_lnk) {
984                         for (; pstk->in_lnkpstk->in_lnk = pstk->in_lnk->snext)
985                                 if (pstk->in_lnk->sname == (char *)p->n_sp)
986                                         break;
987                         if (pstk->in_lnk == NULL)
988                                 uerror("member missing");
989                 } else {
990                         uerror("not a struct/union");
991                 }
992                 break;
993         default:
994                 cerror("mkstack2");
995         }
996         nfree(p);
997         stkpush();
998
999 }
1000
1001 /*
1002  * Initialize a specific element, as per C99.
1003  */
1004 void
1005 desinit(NODE *p)
1006 {
1007         int op = p->n_op;
1008
1009         if (pstk == NULL)
1010                 stkpush(); /* passed end of array */
1011         while (pstk->in_prev && pstk->in_fl == 0)
1012                 pstk = pstk->in_prev/* Empty stack */
1013
1014         if (ISSOU(pstk->in_t))
1015                 pstk->in_lnk = strmemb(pstk->in_sym->sap);
1016
1017         mkstack(p);     /* Setup for assignment */
1018
1019         /* pop one step if SOU, ilbrace will push */
1020         if (op == NAME || op == LB)
1021                 pstk = pstk->in_prev;
1022
1023 #ifdef PCC_DEBUG
1024         if (idebug > 1) {
1025                 printf("desinit e\n");
1026                 prtstk(pstk);
1027         }
1028 #endif
1029 }
1030
1031 /*
1032  * Convert a string to an array of char/wchar for asginit.
1033  */
1034 static void
1035 strcvt(NODE *p)
1036 {
1037         NODE *q = p;
1038         char *s;
1039         int i;
1040
1041 #ifdef mach_arm
1042         /* XXX */
1043         if (p->n_op == UMUL && p->n_left->n_op == ADDROF)
1044                 p = p->n_left->n_left;
1045 #endif
1046
1047         for (s = p->n_sp->sname; *s != 0; ) {
1048                 if (*s++ == '\\') {
1049                         i = esccon(&s);  
1050                 } else
1051                         i = (unsigned char)s[-1];
1052                 asginit(bcon(i));
1053         } 
1054         tfree(q);
1055 }
1056
1057 /*
1058  * Do an assignment to a struct element.
1059  */
1060 void
1061 asginit(NODE *p)
1062 {
1063         int g;
1064
1065 #ifdef PCC_DEBUG
1066         if (idebug)
1067                 printf("asginit %p\n"p);
1068         if (idebug > 1 && p)
1069                 fwalk(peprint0);
1070 #endif
1071
1072         /* convert string to array of char/wchar */
1073         if (p && (DEUNSIGN(p->n_type) == ARY+CHAR ||
1074             p->n_type == ARY+WCHAR_TYPE)) {
1075                 struct instk *is;
1076                 TWORD t;
1077
1078                 t = p->n_type == ARY+WCHAR_TYPE ? ARY+WCHAR_TYPE : ARY+CHAR;
1079                 /*
1080                  * ...but only if next element is ARY+CHAR, otherwise 
1081                  * just fall through.
1082                  */
1083
1084                 /* HACKHACKHACK */
1085                 is = pstk;
1086
1087                 if (pstk == NULL)
1088                         stkpush();
1089                 while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
1090                         stkpush();
1091                 if (pstk->in_prev && 
1092                     (DEUNSIGN(pstk->in_prev->in_t) == t ||
1093                     pstk->in_prev->in_t == t)) {
1094                         pstk = pstk->in_prev;
1095                         if ((g = pstk->in_fl) == 0)
1096                                 pstk->in_fl = 1/* simulate ilbrace */
1097
1098                         strcvt(p);
1099                         if (g == 0)
1100                                 irbrace(); /* will fill with zeroes */
1101                         return;
1102                 } else
1103                         pstk = is/* no array of char */
1104                 /* END HACKHACKHACK */
1105         }
1106
1107         if (p == NULL) { /* only end of compound stmt */
1108                 irbrace();
1109         } else /* assign next element */
1110                 scalinit(p);
1111 }
1112
1113 #ifdef PCC_DEBUG
1114 void
1115 prtstk(struct instk *in)
1116 {
1117         int io = 0;
1118
1119         printf("init stack:\n");
1120         for (; in != NULLin = in->in_prev) {
1121                 for (i = 0i < oi++)
1122                         printf("  ");
1123                 printf("%p) '%s' "inin->in_sym->sname);
1124                 tprint(stdoutin->in_t0);
1125                 printf(" %s "scnames(in->in_sym->sclass));
1126                 if (in->in_df /* && in->in_df->ddim */)
1127                     printf("arydim=%d "in->in_df->ddim);
1128                 printf("ninit=%d "in->in_n);
1129                 if (BTYPE(in->in_t) == STRTY || ISARY(in->in_t))
1130                         printf("stsize=%d ",
1131                             (int)tsize(in->in_tin->in_dfin->in_sym->sap));
1132                 if (in->in_flprintf("{ ");
1133                 printf("soff=%d "in->in_sym->soffset);
1134                 if (in->in_t == STRTY) {
1135                         if (in->in_lnk)
1136                                 printf("curel %s "in->in_lnk->sname);
1137                         else
1138                                 printf("END struct");
1139                 }
1140                 printf("\n");
1141                 o++;
1142         }
1143 }
1144 #endif
1145
1146 /*
1147  * Do a simple initialization.
1148  * At block 0, just print out the value, at higher levels generate
1149  * appropriate code.
1150  */
1151 void
1152 simpleinit(struct symtab *spNODE *p)
1153 {
1154         NODE *q, *r, *nt;
1155         TWORD t;
1156         int sz;
1157
1158         /* May be an initialization of an array of char by a string */
1159         if ((DEUNSIGN(p->n_type) == ARY+CHAR &&
1160             DEUNSIGN(sp->stype) == ARY+CHAR) ||
1161             (DEUNSIGN(p->n_type) == DEUNSIGN(ARY+WCHAR_TYPE) &&
1162             DEUNSIGN(sp->stype) == DEUNSIGN(ARY+WCHAR_TYPE))) {
1163                 /* Handle "aaa" as { 'a', 'a', 'a' } */
1164                 beginit(sp);
1165                 strcvt(p);
1166                 if (csym->sdf->ddim == NOOFFSET)
1167                         scalinit(bcon(0)); /* Null-term arrays */
1168                 endinit(0);
1169                 return;
1170         }
1171
1172         nt = nametree(sp);
1173         switch (sp->sclass) {
1174         case STATIC:
1175         case EXTDEF:
1176                 q = nt;
1177                 locctr(DATAsp);
1178                 defloc(sp);
1179 #ifndef NO_COMPLEX
1180                 if (ANYCX(q) || ANYCX(p)) {
1181                         r = cxop(ASSIGNqp);
1182                         /* XXX must unwind the code generated here */
1183                         /* We can rely on correct code generated */
1184                         p = r->n_left->n_right->n_left;
1185                         r->n_left->n_right->n_left = bcon(0);
1186                         tfree(r);
1187                         r = p->n_left->n_right;
1188                         sz = (int)tsize(r->n_typer->n_dfr->n_ap);
1189                         inval(0szr);
1190                         inval(0szp->n_right->n_right);
1191                         tfree(p);
1192                         break;
1193                 }
1194 #endif
1195                 p = optim(buildtree(ASSIGNntp));
1196 #ifndef WORD_ADDRESSED
1197                 p = optim(rmpconv(p));
1198 #endif
1199                 q = p->n_right;
1200                 t = q->n_type;
1201                 sz = (int)tsize(tq->n_dfq->n_ap);
1202                 inval(0szq);
1203                 tfree(p);
1204                 break;
1205
1206         case AUTO:
1207         case REGISTER:
1208                 if (ISARY(sp->stype))
1209                         cerror("no array init");
1210                 q = nt;
1211 #ifndef NO_COMPLEX
1212
1213                 if (ANYCX(q) || ANYCX(p))
1214                         r = cxop(ASSIGNqp);
1215                 else
1216 #endif
1217                         r = buildtree(ASSIGNqp);
1218                 ecomp(r);
1219                 break;
1220
1221         default:
1222                 uerror("illegal initialization");
1223         }
1224 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-11-01 13:32 +0100