source: mainline/uspace/app/pcc/cc/ccom/init.c@ 8a23fef

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8a23fef was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

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