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