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