new date 20231021
[pcc.git] / cc / cxxcom / init.c
blob957e70a383b244453653a1d709b01da39340ddd7
1 /* $Id: init.c,v 1.6 2015/11/24 17:30:20 ragge Exp $ */
3 /*
4 * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se).
5 * All rights reserved.
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
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.
31 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
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.
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.
64 #include "pass1.h"
65 #include <string.h>
68 * The following machine-dependent routines may be called during
69 * initialization:
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.
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.
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.
90 * The base element(s) of an initialized variable is kept in a linked
91 * list, allocated while initialized.
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.
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.
101 * Position entries are increased when traversing back down into the stack.
105 * Good-to-know entries from symtab:
106 * soffset - # of bits from beginning of this structure.
110 * TO FIX:
111 * - Alignment of structs on like i386 char members.
115 * Struct used in array initialisation.
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 } *pstk, pbase;
127 int doing_init, statinit;
128 static struct symtab *csym;
130 #ifdef PCC_DEBUG
131 static void prtstk(struct instk *in);
132 #endif
135 * Linked lists for initializations.
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 */
144 struct llist {
145 SLIST_ENTRY(llist) next;
146 CONSZ begsz; /* bit offset of this entry */
147 struct ilist *il;
149 static SLIST_HEAD(llh, llist) lpole;
150 static CONSZ basesz;
151 static int numents; /* # of array entries allocated */
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;
162 static struct ilist *
163 getil(struct ilist *next, CONSZ b, int sz, NODE *n)
165 struct ilist *il = tmpalloc(sizeof(struct ilist));
167 il->off = b;
168 il->fsz = sz;
169 il->n = n;
170 il->next = next;
171 return il;
175 * Allocate a new struct defining a block of initializers appended to the
176 * end of the llist. Return that entry.
178 static struct llist *
179 getll(void)
181 struct llist *ll;
183 ll = tmpalloc(sizeof(struct llist));
184 ll->begsz = numents * basesz;
185 ll->il = NULL;
186 SLIST_INSERT_LAST(&lpole, ll, next);
187 numents++;
188 return ll;
192 * Return structure containing off bitnumber.
193 * Allocate more entries, if needed.
195 static struct llist *
196 setll(OFFSZ off)
198 struct llist *ll = NULL;
200 /* Ensure that we have enough entries */
201 while (off >= basesz * numents)
202 ll = getll();
204 if (ll != NULL && ll->begsz <= off && ll->begsz + basesz > off)
205 return ll;
207 SLIST_FOREACH(ll, &lpole, next)
208 if (ll->begsz <= off && ll->begsz + basesz > off)
209 break;
210 return ll; /* ``cannot fail'' */
212 char *astypnames[] = { 0, 0, "\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",
217 void
218 inval(CONSZ off, int fsz, NODE *p)
220 struct symtab *sp;
221 CONSZ val;
222 TWORD t;
224 if (p->n_op != ICON && p->n_op != FCON) {
225 uerror("constant required");
226 return;
228 if (p->n_type == BOOL) {
229 if ((U_CONSZ)glval(p) > 1)
230 slval(p, 1);
231 p->n_type = BOOL_TYPE;
233 if (ninval(off, fsz, p))
234 return; /* dealt with in local.c */
235 t = p->n_type;
236 if (t > BTMASK)
237 t = INTPTR;
239 val = (CONSZ)(glval(p) & SZMASK(sztable[t]));
240 if (t <= ULONGLONG) {
241 sp = p->n_sp;
242 printf("%s ",astypnames[t]);
243 if (val || sp == NULL)
244 printf(CONFMT, val);
245 if (val && sp != NULL)
246 printf("+");
247 if (sp != NULL) {
248 if ((sp->sclass == STATIC && sp->slevel > 0)) {
249 printf(LABFMT, sp->soffset);
250 } else
251 printf("%s", sp->soname ?
252 sp->soname : exname(sp->sname));
254 printf("\n");
255 } else
256 cerror("inval: unhandled type %d", (int)t);
259 #ifndef MYBFINIT
261 static int inbits;
262 static CONSZ xinval;
264 * Initialize a bitfield.
265 * XXX - use U_CONSZ?
267 void
268 infld(CONSZ off, int fsz, CONSZ val)
270 #ifdef PCC_DEBUG
271 if (idebug)
272 printf("infld off " CONFMT ", fsz %d, val " CONFMT " inbits %d\n",
273 off, fsz, val, inbits);
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], (CONSZ)(xinval & SZMASK(SZCHAR)));
282 fsz -= shsz;
283 val &= SZMASK(fsz);
284 xinval = inbits = 0;
286 if (fsz) {
287 xinval = (xinval << fsz) | val;
288 inbits += fsz;
290 #else
291 while (fsz + inbits >= SZCHAR) {
292 int shsz = SZCHAR-inbits;
293 xinval |= (val << inbits);
294 printf("%s " CONFMT "\n",
295 astypnames[CHAR], (CONSZ)(xinval & SZMASK(SZCHAR)));
296 fsz -= shsz;
297 val >>= shsz;
298 xinval = inbits = 0;
300 if (fsz) {
301 xinval |= (val << inbits);
302 inbits += fsz;
304 #endif
307 char *asspace = "\t.space";
310 * set fsz bits in sequence to zero.
312 void
313 zbits(OFFSZ off, int fsz)
315 int m;
317 #ifdef PCC_DEBUG
318 if (idebug)
319 printf("zbits off " CONFMT ", fsz %d inbits %d\n", off, fsz, inbits);
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;
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], (CONSZ)(xinval & SZMASK(SZCHAR)));
346 xinval = inbits = 0;
349 #endif
350 if (fsz >= SZCHAR) {
351 printf("%s %d\n", asspace, fsz/SZCHAR);
352 fsz -= (fsz/SZCHAR) * SZCHAR;
354 if (fsz) {
355 xinval = 0;
356 inbits = fsz;
359 #endif
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.
366 void
367 beginit(struct symtab *sp)
369 struct initctx *ict;
370 struct instk *is = &pbase;
372 #ifdef PCC_DEBUG
373 if (idebug)
374 printf("beginit(%p), sclass %s\n", sp, scnames(sp->sclass));
375 #endif
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));
393 csym = sp;
395 numents = 0; /* no entries in array list */
396 if (ISARY(sp->stype)) {
397 basesz = tsize(DECREF(sp->stype), sp->sdf+1, sp->sap);
398 if (basesz == 0) {
399 uerror("array has incomplete type");
400 basesz = SZINT;
402 } else
403 basesz = tsize(sp->stype, sp->sdf, sp->sap);
404 SLIST_INIT(&lpole);
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++;
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.
429 static void
430 stkpush(void)
432 struct instk *is;
433 struct symtab *sq, *sp;
434 TWORD t;
436 if (pstk == NULL) {
437 sp = csym;
438 t = 0;
439 } else {
440 t = pstk->in_t;
441 sp = pstk->in_sym;
444 #ifdef PCC_DEBUG
445 if (idebug) {
446 printf("stkpush: '%s' %s ", sp->sname, scnames(sp->sclass));
447 tprint(t, 0);
449 #endif
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.
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;
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--;
484 is->in_df = pstk->in_df+1;
485 } else
486 uerror("too many left braces");
487 is->in_prev = pstk;
488 pstk = is;
490 #ifdef PCC_DEBUG
491 if (idebug) {
492 printf(" newtype ");
493 tprint(is->in_t, 0);
494 printf("\n");
496 #endif
500 * pop down to either next level that can handle a new initializer or
501 * to the next braced level.
503 static void
504 stkpop(void)
506 #ifdef PCC_DEBUG
507 if (idebug)
508 printf("stkpop\n");
509 #endif
510 for (; pstk; pstk = 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;
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 */
527 #ifdef PCC_DEBUG
528 if (idebug > 1)
529 prtstk(pstk);
530 #endif
534 * Count how many elements an array may consist of.
536 static int
537 acalc(struct instk *is, int n)
539 if (is == NULL || !ISARY(is->in_t))
540 return 0;
541 return acalc(is->in_prev, n * is->in_df->ddim) + n * is->in_n;
545 * Find current bit offset of the top element on the stack from
546 * the beginning of the aggregate.
548 static CONSZ
549 findoff(void)
551 struct instk *is;
552 OFFSZ off;
554 #ifdef PCC_DEBUG
555 if (ISARY(pstk->in_t))
556 cerror("findoff on bad type %x", pstk->in_t);
557 #endif
560 * Offset calculations. If:
561 * - previous type is STRTY, soffset has in-struct offset.
562 * - this type is ARY, offset is ninit*stsize.
564 for (off = 0, is = pstk; is; is = 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(t, is->in_sym->sdf, is->in_sym->sap);
578 off += o * acalc(is, 1);
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;
587 #ifdef PCC_DEBUG
588 if (idebug>1) {
589 printf("findoff: off " CONFMT "\n", off);
590 prtstk(pstk);
592 #endif
593 return off;
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.
601 static void
602 nsetval(CONSZ off, int fsz, NODE *p)
604 struct llist *ll;
605 struct ilist *il;
607 if (idebug>1)
608 printf("setval: off " CONFMT " fsz %d p %p\n", off, fsz, p);
610 if (fsz == 0)
611 return;
613 ll = setll(off);
614 off -= ll->begsz;
615 if (ll->il == NULL) {
616 ll->il = getil(NULL, off, fsz, p);
617 } else {
618 il = ll->il;
619 if (il->off > off) {
620 ll->il = getil(ll->il, off, fsz, p);
621 } else {
622 for (il = ll->il; il->next; il = 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->next, off, fsz, p);
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.
641 CONSZ
642 scalinit(NODE *p)
644 CONSZ woff;
645 NODE *q;
646 int fsz;
648 #ifdef PCC_DEBUG
649 if (idebug > 2) {
650 printf("scalinit(%p)\n", p);
651 fwalk(p, eprint, 0);
652 prtstk(pstk);
654 #endif
656 if (nerrors)
657 return 0;
659 p = optim(p);
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
667 /* Out of elements? */
668 if (pstk == NULL) {
669 uerror("excess of initializing elements");
670 return 0;
674 * Get to the simple type if needed.
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->sap, p->n_ap))
681 break;
684 if (ISSOU(pstk->in_t) == 0) {
685 /* let buildtree do typechecking (and casting) */
686 q = block(NAME, NIL,NIL, pstk->in_t, pstk->in_df,
687 pstk->in_sym->sap);
688 p = buildtree(ASSIGN, q, p);
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);
700 woff = findoff();
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_t, pstk->in_sym->sdf,
707 pstk->in_sym->sap);
709 nsetval(woff, fsz, q);
711 stkpop();
712 #ifdef PCC_DEBUG
713 if (idebug > 2) {
714 printf("scalinit e(%p)\n", q);
716 #endif
717 return woff;
721 * Generate code to insert a value into a bitfield.
723 static void
724 insbf(OFFSZ off, int fsz, int val)
726 struct symtab sym;
727 NODE *p, *r;
728 TWORD typ;
730 #ifdef PCC_DEBUG
731 if (idebug > 1)
732 printf("insbf: off " CONFMT " fsz %d val %d\n", off, fsz, val);
733 #endif
735 if (fsz == 0)
736 return;
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(ADDROF, nametree(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, &sym, typ);
752 p = block(STREF, p, r, INT, 0, 0);
753 ecomp(buildtree(ASSIGN, stref(p), bcon(val)));
757 * Clear a bitfield, starting at off and size fsz.
759 static void
760 clearbf(OFFSZ off, OFFSZ fsz)
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(off, ba, 0);
768 off += ba;
769 fsz -= ba;
771 while (fsz >= SZCHAR) {
772 insbf(off, SZCHAR, 0);
773 off += SZCHAR;
774 fsz -= SZCHAR;
776 if (fsz)
777 insbf(off, fsz, 0);
781 * final step of initialization.
782 * print out init nodes and generate copy code (if needed).
784 void
785 endinit(int seg)
787 struct llist *ll;
788 struct ilist *il;
789 int fsz;
790 OFFSZ lastoff, tbit;
792 #ifdef PCC_DEBUG
793 if (idebug)
794 printf("endinit()\n");
795 #endif
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);
805 } else
806 tbit = tsize(csym->stype, csym->sdf, csym->sap);
808 /* Setup symbols */
809 if (csym->sclass != AUTO) {
810 locctr(seg ? UDATA : DATA, csym);
811 defloc(csym);
814 /* Traverse all entries and print'em out */
815 lastoff = 0;
816 SLIST_FOREACH(ll, &lpole, next) {
817 for (il = ll->il; il; il = il->next) {
818 #ifdef PCC_DEBUG
819 if (idebug > 1) {
820 printf("off " CONFMT " size %d val " CONFMT " type ",
821 ll->begsz+il->off, il->fsz, glval(il->n));
822 tprint(il->n->n_type, 0);
823 printf("\n");
825 #endif
826 fsz = il->fsz;
827 if (csym->sclass == AUTO) {
828 struct symtab sym;
829 NODE *p, *r, *n;
831 if (ll->begsz + il->off > lastoff)
832 clearbf(lastoff,
833 (ll->begsz + il->off) - lastoff);
835 /* Fake a struct reference */
836 p = buildtree(ADDROF, nametree(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, &sym, INT);
845 p = block(STREF, p, r, INT, 0, 0);
846 ecomp(buildtree(ASSIGN, stref(p), il->n));
847 if (fsz < 0)
848 fsz = -fsz;
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->off, fsz, glval(il->n));
857 } else
858 inval(il->off, fsz, il->n);
859 tfree(il->n);
861 lastoff = ll->begsz + il->off + fsz;
864 if (csym->sclass == AUTO) {
865 clearbf(lastoff, tbit-lastoff);
866 } else
867 zbits(lastoff, tbit-lastoff);
869 doing_init--;
870 if (csym->sclass == STATIC || csym->sclass == EXTDEF)
871 statinit--;
872 endictx();
875 void
876 endictx(void)
878 struct initctx *ict = inilnk;
880 if (ict == NULL)
881 return;
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
896 * process an initializer's left brace
898 void
899 ilbrace(void)
901 #ifdef PCC_DEBUG
902 if (idebug)
903 printf("ilbrace()\n");
904 #endif
906 if (pstk == NULL)
907 return;
909 stkpush();
910 pstk->in_fl = 1; /* mark lbrace */
911 #ifdef PCC_DEBUG
912 if (idebug > 1)
913 prtstk(pstk);
914 #endif
918 * called when a '}' is seen
920 void
921 irbrace(void)
923 #ifdef PCC_DEBUG
924 if (idebug)
925 printf("irbrace()\n");
926 if (idebug > 2)
927 prtstk(pstk);
928 #endif
930 if (pstk == NULL)
931 return;
933 /* Got right brace, search for corresponding in the stack */
934 for (; pstk->in_prev != NULL; pstk = pstk->in_prev) {
935 if(!pstk->in_fl)
936 continue;
938 /* we have one now */
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;
948 stkpop();
949 return;
954 * Create a new init stack based on given elements.
956 static void
957 mkstack(NODE *p)
960 #ifdef PCC_DEBUG
961 if (idebug) {
962 printf("mkstack: %p\n", p);
963 if (idebug > 1 && p)
964 fwalk(p, eprint, 0);
966 #endif
968 if (p == NULL)
969 return;
970 mkstack(p->n_left);
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)glval(p->n_right);
979 nfree(p->n_right);
980 break;
982 case NAME:
983 if (pstk->in_lnk) {
984 for (; pstk->in_lnk; pstk->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");
992 break;
993 default:
994 cerror("mkstack2");
996 nfree(p);
997 stkpush();
1002 * Initialize a specific element, as per C99.
1004 void
1005 desinit(NODE *p)
1007 int op = p->n_op;
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 */
1014 if (ISSOU(pstk->in_t))
1015 pstk->in_lnk = strmemb(pstk->in_sym->sap);
1017 mkstack(p); /* Setup for assignment */
1019 /* pop one step if SOU, ilbrace will push */
1020 if (op == NAME || op == LB)
1021 pstk = pstk->in_prev;
1023 #ifdef PCC_DEBUG
1024 if (idebug > 1) {
1025 printf("desinit e\n");
1026 prtstk(pstk);
1028 #endif
1032 * Convert a string to an array of char/wchar for asginit.
1034 static void
1035 strcvt(NODE *p)
1037 NODE *q = p;
1038 char *s;
1039 int i;
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
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));
1054 tfree(q);
1058 * Do an assignment to a struct element.
1060 void
1061 asginit(NODE *p)
1063 int g;
1065 #ifdef PCC_DEBUG
1066 if (idebug)
1067 printf("asginit %p\n", p);
1068 if (idebug > 1 && p)
1069 fwalk(p, eprint, 0);
1070 #endif
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;
1078 t = p->n_type == ARY+WCHAR_TYPE ? ARY+WCHAR_TYPE : ARY+CHAR;
1080 * ...but only if next element is ARY+CHAR, otherwise
1081 * just fall through.
1084 /* HACKHACKHACK */
1085 is = pstk;
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 */
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 */
1107 if (p == NULL) { /* only end of compound stmt */
1108 irbrace();
1109 } else /* assign next element */
1110 scalinit(p);
1113 #ifdef PCC_DEBUG
1114 void
1115 prtstk(struct instk *in)
1117 int i, o = 0;
1119 printf("init stack:\n");
1120 for (; in != NULL; in = in->in_prev) {
1121 for (i = 0; i < o; i++)
1122 printf(" ");
1123 printf("%p) '%s' ", in, in->in_sym->sname);
1124 tprint(in->in_t, 0);
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_t, in->in_df, in->in_sym->sap));
1132 if (in->in_fl) printf("{ ");
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");
1140 printf("\n");
1141 o++;
1144 #endif
1147 * Do a simple initialization.
1148 * At block 0, just print out the value, at higher levels generate
1149 * appropriate code.
1151 void
1152 simpleinit(struct symtab *sp, NODE *p)
1154 NODE *q, *r, *nt;
1155 TWORD t;
1156 int sz;
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;
1172 nt = nametree(sp);
1173 switch (sp->sclass) {
1174 case STATIC:
1175 case EXTDEF:
1176 q = nt;
1177 locctr(DATA, sp);
1178 defloc(sp);
1179 #ifndef NO_COMPLEX
1180 if (ANYCX(q) || ANYCX(p)) {
1181 r = cxop(ASSIGN, q, p);
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_type, r->n_df, r->n_ap);
1189 inval(0, sz, r);
1190 inval(0, sz, p->n_right->n_right);
1191 tfree(p);
1192 break;
1194 #endif
1195 p = optim(buildtree(ASSIGN, nt, p));
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(t, q->n_df, q->n_ap);
1202 inval(0, sz, q);
1203 tfree(p);
1204 break;
1206 case AUTO:
1207 case REGISTER:
1208 if (ISARY(sp->stype))
1209 cerror("no array init");
1210 q = nt;
1211 #ifndef NO_COMPLEX
1213 if (ANYCX(q) || ANYCX(p))
1214 r = cxop(ASSIGN, q, p);
1215 else
1216 #endif
1217 r = buildtree(ASSIGN, q, p);
1218 ecomp(r);
1219 break;
1221 default:
1222 uerror("illegal initialization");