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