1 /* $Id: init.c,v 1.62 2011/02/19 17:23:39 ragge Exp $ */
4 * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se).
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
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
46 * Neither the name of Caldera International, Inc. nor the names of other
47 * contributors may be used to endorse or promote products derived from
48 * this software without specific prior written permission.
50 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
51 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
55 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
60 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
68 * The following machine-dependent routines may be called during
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
79 * Initialization may be of different kind:
80 * - Initialization at compile-time, all values are constants and laid
81 * out in memory. Static or extern variables outside functions.
82 * - Initialization at run-time, written to their values as code.
84 * Currently run-time-initialized variables are only initialized by using
85 * move instructions. An optimization might be to detect that it is
86 * initialized with constants and therefore copied from readonly memory.
90 * The base element(s) of an initialized variable is kept in a linked
91 * list, allocated while initialized.
93 * When a scalar is found, entries are popped of the instk until it's
94 * possible to find an entry for a new scalar; then onstk() is called
95 * to get the correct type and size of that scalar.
97 * If a right brace is found, pop the stack until a matching left brace
98 * were found while filling the elements with zeros. This left brace is
99 * also marking where the current level is for designated initializations.
101 * Position entries are increased when traversing back down into the stack.
105 * Good-to-know entries from symtab:
106 * soffset - # of bits from beginning of this structure.
111 * - Alignment of structs on like i386 char members.
117 * Struct used in array initialisation.
119 static 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 {} */
129 static struct symtab
*csym
;
132 static void prtstk(struct instk
*in
);
136 * Linked lists for initializations.
140 CONSZ off
; /* bit offset of this entry */
141 int fsz
; /* bit size of this entry */
142 NODE
*n
; /* node containing this data info */
146 SLIST_ENTRY(llist
) next
;
147 CONSZ begsz
; /* bit offset of this entry */
150 static SLIST_HEAD(llh
, llist
) lpole
;
152 static int numents
; /* # of array entries allocated */
154 static struct initctx
{
155 struct initctx
*prev
;
163 static struct ilist
*
164 getil(struct ilist
*next
, CONSZ b
, int sz
, NODE
*n
)
166 struct ilist
*il
= tmpalloc(sizeof(struct ilist
));
176 * Allocate a new struct defining a block of initializers appended to the
177 * end of the llist. Return that entry.
179 static struct llist
*
184 ll
= tmpalloc(sizeof(struct llist
));
185 ll
->begsz
= numents
* basesz
;
187 SLIST_INSERT_LAST(&lpole
, ll
, next
);
193 * Return structure containing off bitnumber.
194 * Allocate more entries, if needed.
196 static struct llist
*
199 struct llist
*ll
= NULL
;
201 /* Ensure that we have enough entries */
202 while (off
>= basesz
* numents
)
205 if (ll
!= NULL
&& ll
->begsz
<= off
&& ll
->begsz
+ basesz
> off
)
208 SLIST_FOREACH(ll
, &lpole
, next
)
209 if (ll
->begsz
<= off
&& ll
->begsz
+ basesz
> off
)
211 return ll
; /* ``cannot fail'' */
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.
220 beginit(struct symtab
*sp
)
223 struct instk
*is
= &pbase
;
227 printf("beginit(%p), sclass %s\n", sp
, scnames(sp
->sclass
));
233 printf("beginit: saving ctx pstk %p\n", pstk
);
235 /* save old context */
236 ict
= tmpalloc(sizeof(struct initctx
));
242 ict
->basesz
= basesz
;
243 ict
->numents
= numents
;
244 is
= tmpalloc(sizeof(struct instk
));
248 numents
= 0; /* no entries in array list */
249 if (ISARY(sp
->stype
)) {
250 basesz
= tsize(DECREF(sp
->stype
), sp
->sdf
+1, sp
->sap
);
252 uerror("array has incomplete type");
256 basesz
= tsize(DECREF(sp
->stype
), sp
->sdf
, sp
->sap
);
260 if (ISSOU(sp
->stype
)) {
261 is
->in_lnk
= strmemb(sp
->sap
);
265 is
->in_t
= sp
->stype
;
274 * Push a new entry on the initializer stack.
275 * The new entry will be "decremented" to the new sub-type of the previous
277 * Popping of entries is done elsewhere.
283 struct symtab
*sq
, *sp
;
296 printf("stkpush: '%s' %s ", sp
->sname
, scnames(sp
->sclass
));
297 tprint(stdout
, t
, 0);
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.
306 is
= tmpalloc(sizeof(struct instk
));
311 is
->in_lnk
= ISSOU(sp
->stype
) ? strmemb(sp
->sap
) : NULL
;
312 is
->in_t
= sp
->stype
;
315 } else if (ISSOU(t
)) {
318 uerror("excess of initializing elements");
320 is
->in_lnk
= ISSOU(sq
->stype
) ? strmemb(sq
->sap
) : NULL
;
321 is
->in_t
= sq
->stype
;
325 } else if (ISARY(t
)) {
326 is
->in_lnk
= ISSOU(DECREF(t
)) ? strmemb(pstk
->in_sym
->sap
) : 0;
327 is
->in_t
= DECREF(t
);
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");
334 is
->in_df
= pstk
->in_df
+1;
336 uerror("too many left braces");
343 tprint(stdout
, is
->in_t
, 0);
350 * pop down to either next level that can handle a new initializer or
351 * to the next braced level.
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
)
366 if (ISSOU(pstk
->in_t
) && pstk
->in_fl
)
368 if (ISARY(pstk
->in_t
)) {
372 if (pstk
->in_df
->ddim
== NOOFFSET
||
373 pstk
->in_n
< pstk
->in_df
->ddim
)
374 break; /* ger more elements */
384 * Count how many elements an array may consist of.
387 acalc(struct instk
*is
, int n
)
389 if (is
== NULL
|| !ISARY(is
->in_t
))
391 return acalc(is
->in_prev
, n
* is
->in_df
->ddim
) + n
* is
->in_n
;
395 * Find current bit offset of the top element on the stack from
396 * the beginning of the aggregate.
405 if (ISARY(pstk
->in_t
))
406 cerror("findoff on bad type %x", pstk
->in_t
);
410 * Offset calculations. If:
411 * - previous type is STRTY, soffset has in-struct offset.
412 * - this type is ARY, offset is ninit*stsize.
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 */
424 o
= SZPOINT(t
); /* XXX use tsize() */
426 o
= tsize(t
, is
->in_sym
->sdf
, is
->in_sym
->sap
);
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
;
439 printf("findoff: off %lld\n", off
);
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.
452 nsetval(CONSZ off
, int fsz
, NODE
*p
)
458 printf("setval: off %lld fsz %d p %p\n", off
, fsz
, p
);
465 if (ll
->il
== NULL
) {
466 ll
->il
= getil(NULL
, off
, fsz
, p
);
470 ll
->il
= getil(ll
->il
, off
, fsz
, p
);
472 for (il
= ll
->il
; il
->next
; il
= il
->next
)
473 if (il
->off
<= off
&& il
->next
->off
> off
)
475 if (il
->off
== off
) {
480 il
->next
= getil(il
->next
, off
, fsz
, p
);
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.
500 printf("scalinit(%p)\n", p
);
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");
517 /* Out of elements? */
519 uerror("excess of initializing elements");
524 * Get to the simple type if needed.
526 while (ISSOU(pstk
->in_t
) || ISARY(pstk
->in_t
)) {
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
))
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
,
538 p
= buildtree(ASSIGN
, q
, p
);
540 q
= optim(p
->n_right
);
547 /* bitfield sizes are special */
548 if (pstk
->in_sym
->sclass
& FIELD
)
549 fsz
= -(pstk
->in_sym
->sclass
& FLDSIZ
);
551 fsz
= (int)tsize(pstk
->in_t
, pstk
->in_sym
->sdf
,
554 nsetval(woff
, fsz
, q
);
559 printf("scalinit e(%p)\n", q
);
566 * Generate code to insert a value into a bitfield.
569 insbf(OFFSZ off
, int fsz
, int val
)
577 printf("insbf: off %lld fsz %d val %d\n", off
, fsz
, val
);
583 /* small opt: do char instead of bf asg */
584 if ((off
& (ALCHAR
-1)) == 0 && fsz
== SZCHAR
)
588 /* Fake a struct reference */
589 p
= buildtree(ADDROF
, nametree(csym
), NIL
);
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
)));
602 * Clear a bitfield, starting at off and size fsz.
605 clearbf(OFFSZ off
, OFFSZ fsz
)
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
);
616 while (fsz
>= SZCHAR
) {
617 insbf(off
, SZCHAR
, 0);
626 * final step of initialization.
627 * print out init nodes and generate copy code (if needed).
639 printf("endinit()\n");
642 if (csym
->sclass
!= AUTO
)
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
);
654 tbit
= tsize(csym
->stype
, csym
->sdf
, csym
->sap
);
656 /* Traverse all entries and print'em out */
658 SLIST_FOREACH(ll
, &lpole
, next
) {
659 for (il
= ll
->il
; il
; il
= il
->next
) {
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);
669 if (csym
->sclass
== AUTO
) {
673 if (ll
->begsz
+ il
->off
> lastoff
)
675 (ll
->begsz
+ il
->off
) - lastoff
);
677 /* Fake a struct reference */
678 p
= buildtree(ADDROF
, nametree(csym
), NIL
);
680 sym
.stype
= n
->n_type
;
681 sym
.squal
= n
->n_qual
;
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
));
693 if (ll
->begsz
+ il
->off
> lastoff
)
695 (ll
->begsz
+ il
->off
) - lastoff
);
698 infld(il
->off
, fsz
, il
->n
->n_lval
);
700 ninval(il
->off
, fsz
, il
->n
);
703 lastoff
= ll
->begsz
+ il
->off
+ fsz
;
706 if (csym
->sclass
== AUTO
) {
707 clearbf(lastoff
, tbit
-lastoff
);
709 zbits(lastoff
, tbit
-lastoff
);
717 struct initctx
*ict
= inilnk
;
725 basesz
= ict
->basesz
;
726 numents
= ict
->numents
;
727 inilnk
= inilnk
->prev
;
730 printf("endinit: restoring ctx pstk %p\n", pstk
);
735 * process an initializer's left brace
743 printf("ilbrace()\n");
750 pstk
->in_fl
= 1; /* mark lbrace */
758 * called when a '}' is seen
765 printf("irbrace()\n");
773 /* Got right brace, search for corresponding in the stack */
774 for (; pstk
->in_prev
!= NULL
; pstk
= pstk
->in_prev
) {
778 /* we have one now */
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
;
794 * Create a new init stack based on given elements.
802 printf("mkstack: %p\n", p
);
813 case LB
: /* Array index */
814 if (p
->n_right
->n_op
!= ICON
)
816 if (!ISARY(pstk
->in_t
))
817 uerror("array indexing non-array");
818 pstk
->in_n
= (int)p
->n_right
->n_lval
;
824 for (; pstk
->in_lnk
; pstk
->in_lnk
= pstk
->in_lnk
->snext
)
825 if (pstk
->in_lnk
->sname
== (char *)p
->n_sp
)
827 if (pstk
->in_lnk
== NULL
)
828 uerror("member missing");
830 uerror("not a struct/union");
842 * Initialize a specific element, as per C99.
850 stkpush(); /* passed end of array */
851 while (pstk
->in_prev
&& pstk
->in_fl
== 0)
852 pstk
= pstk
->in_prev
; /* Empty stack */
854 if (ISSOU(pstk
->in_t
))
855 pstk
->in_lnk
= strmemb(pstk
->in_sym
->sap
);
857 mkstack(p
); /* Setup for assignment */
859 /* pop one step if SOU, ilbrace will push */
860 if (op
== NAME
|| op
== LB
)
861 pstk
= pstk
->in_prev
;
865 printf("desinit e\n");
872 * Convert a string to an array of char/wchar for asginit.
883 if (p
->n_op
== UMUL
&& p
->n_left
->n_op
== ADDROF
)
884 p
= p
->n_left
->n_left
;
887 for (s
= p
->n_sp
->sname
; *s
!= 0; ) {
891 i
= (unsigned char)s
[-1];
898 * Do an assignment to a struct element.
907 printf("asginit %p\n", p
);
912 /* convert string to array of char/wchar */
913 if (p
&& (DEUNSIGN(p
->n_type
) == ARY
+CHAR
||
914 p
->n_type
== ARY
+WCHAR_TYPE
)) {
917 t
= p
->n_type
== ARY
+WCHAR_TYPE
? ARY
+WCHAR_TYPE
: ARY
+CHAR
;
919 * ...but only if next element is ARY+CHAR, otherwise
924 struct instk
*is
= pstk
;
928 while (ISSOU(pstk
->in_t
) || ISARY(pstk
->in_t
))
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 */
939 irbrace(); /* will fill with zeroes */
942 pstk
= is
; /* no array of char */
943 /* END HACKHACKHACK */
946 if (p
== NULL
) { /* only end of compound stmt */
948 } else /* assign next element */
954 prtstk(struct instk
*in
)
958 printf("init stack:\n");
959 for (; in
!= NULL
; in
= in
->in_prev
) {
960 for (i
= 0; i
< o
; i
++)
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
))
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
) {
975 printf("curel %s ", in
->in_lnk
->sname
);
977 printf("END struct");
986 * Do a simple initialization.
987 * At block 0, just print out the value, at higher levels generate
991 simpleinit(struct symtab
*sp
, NODE
*p
)
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' } */
1005 if (csym
->sdf
->ddim
== NOOFFSET
)
1006 scalinit(bcon(0)); /* Null-term arrays */
1012 switch (sp
->sclass
) {
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);
1025 r
= p
->n_left
->n_right
;
1026 sz
= (int)tsize(r
->n_type
, r
->n_df
, r
->n_ap
);
1028 ninval(0, sz
, p
->n_right
->n_right
);
1033 p
= optim(buildtree(ASSIGN
, nt
, p
));
1037 sz
= (int)tsize(t
, q
->n_df
, q
->n_ap
);
1044 if (ISARY(sp
->stype
))
1045 cerror("no array init");
1049 if (ANYCX(q
) || ANYCX(p
))
1050 r
= cxop(ASSIGN
, q
, p
);
1053 r
= buildtree(ASSIGN
, q
, p
);
1058 uerror("illegal initialization");