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