init.c (10494B)
1 #include <assert.h> 2 #include <stdint.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include <scc/cstd.h> 7 #include <scc/scc.h> 8 #include "cc1.h" 9 10 #define NOLIST 0 11 #define INLIST 1 12 13 14 typedef struct init Init; 15 16 struct designator { 17 long long pos; 18 Node *expr; 19 struct designator *next; 20 }; 21 22 struct init { 23 unsigned long long pos; 24 unsigned long long max; 25 struct designator *tail; 26 struct designator *head; 27 }; 28 29 int disstring; 30 31 static long long 32 arydesig(Type *tp, Init *ip) 33 { 34 35 long long npos; 36 Node *np; 37 38 if (tp->op != ARY) 39 errorp("array index in non-array initializer"); 40 41 next(); 42 if ((np = iconstexpr()) == NULL) { 43 errorp("array index in initializer not of integer type"); 44 npos = 0; 45 } else { 46 npos = np->sym->u.i; 47 } 48 49 if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) { 50 errorp("array index in initializer exceeds array bounds"); 51 npos = 0; 52 } 53 freetree(np); 54 expect(']'); 55 return npos; 56 } 57 58 static long long 59 fielddesig(Type *tp, Init *ip) 60 { 61 int ons; 62 Symbol *sym, **p; 63 64 if (!(tp->prop & TAGGREG)) 65 errorp("field name not in record or union initializer"); 66 ons = namespace; 67 namespace = tp->ns; 68 next(); 69 namespace = ons; 70 if (yytoken != IDEN) 71 unexpected(); 72 sym = yylval.sym; 73 next(); 74 if ((sym->flags & SDECLARED) == 0) { 75 errorp("unknown field '%s' specified in initializer", 76 sym->name); 77 return -1; 78 } 79 for (p = tp->p.fields; *p != sym; ++p) 80 ; 81 return p - tp->p.fields; 82 } 83 84 static Init * 85 init(Init *ip) 86 { 87 ip->tail = ip->head = NULL; 88 ip->pos = ip->max = 0; 89 return ip; 90 } 91 92 static Node * 93 str2ary(Type *tp) 94 { 95 char *s; 96 Rune *rs; 97 Node *np; 98 Type *btp = tp->type; 99 Symbol *str, *sym; 100 long long i, olen, len; 101 102 disstring = 1; 103 np = assign(); 104 disstring = 0; 105 str = np->left->sym; 106 107 len = tp->n.elem; 108 olen = str->type->n.elem-1; 109 if (!(tp->prop & TDEFINED)) { 110 len = tp->n.elem = olen+1; 111 deftype(tp); 112 } else if (len < olen) { 113 warn("initializer-string for array of chars is too long"); 114 } 115 116 if (str->flags & SSTRING) { 117 if (btp != chartype && btp != uchartype && btp != schartype) 118 goto wrong; 119 s = str->u.s; 120 sym = newstring(NULL, len); 121 } else { 122 if (btp->size != wchartype->size) 123 goto wrong; 124 rs = str->u.rs; 125 sym = newrstring(NULL, len); 126 } 127 128 for (i = 0; i < len; i++) { 129 if (str->flags & SSTRING) 130 sym->u.s[i] = (i < olen) ? *s++ : '\0'; 131 else 132 sym->u.rs[i] = (i < olen) ? *rs++ : L'\0'; 133 } 134 135 assert(np->op == OADDR); 136 np->left->sym = sym; 137 np->left->type = sym->type; 138 np->sym = sym; 139 np->type = sym->type; 140 141 return np; 142 143 wrong: 144 errorp("array of inappropriate type initialized from string constant"); 145 return constnode(zero); 146 } 147 148 static Node *initlist(Type *); 149 150 static Node * 151 initialize(Type *tp, int inlist) 152 { 153 Node *np; 154 Symbol *sym; 155 156 if (tp->op == ARY && yytoken == STRING) 157 return str2ary(tp); 158 159 if (yytoken == '{' || inlist && (tp->op == STRUCT || tp->op == ARY)) 160 return initlist(tp); 161 162 np = assign(); 163 if (!eqtype(tp, np->type, EQUIV)) { 164 np = convert(decay(np), tp, 0); 165 if (!np) { 166 errorp("incorrect initializer"); 167 return constnode(zero); 168 } 169 } 170 171 return simplify(np); 172 } 173 174 static Node * 175 mkcompound(Init *ip, Type *tp) 176 { 177 Node **v, **p, *np; 178 size_t n; 179 struct designator *dp, *next; 180 Symbol *sym; 181 int isconst = 1; 182 183 if (tp->op == UNION) { 184 np = NULL; 185 v = xmalloc(sizeof(*v)); 186 for (dp = ip->head; dp; dp = next) { 187 freetree(np); 188 np = dp->expr; 189 next = dp->next; 190 free(dp); 191 } 192 if ((np->flags & NCONST) == 0) 193 isconst = 0; 194 *v = np; 195 } else { 196 n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max; 197 if (n == 0) { 198 v = NULL; 199 } else if (n > SIZE_MAX / sizeof(*v)) { 200 errorp("compound literal too big"); 201 return constnode(zero); 202 } else { 203 n *= sizeof(*v); 204 v = memset(xmalloc(n), 0, n); 205 206 for (dp = ip->head; dp; dp = next) { 207 p = &v[dp->pos]; 208 freetree(*p); 209 np = dp->expr; 210 *p = np; 211 if ((np->flags & NCONST) == 0) 212 isconst = 0; 213 next = dp->next; 214 free(dp); 215 } 216 } 217 } 218 219 sym = newsym(NS_IDEN, NULL); 220 sym->u.init = v; 221 sym->type = tp; 222 sym->flags |= SINITLST; 223 224 return (isconst ? constnode : varnode)(sym); 225 } 226 227 static void 228 newdesig(Init *ip, Node *np) 229 { 230 struct designator *dp; 231 232 dp = xmalloc(sizeof(*dp)); 233 dp->pos = ip->pos; 234 dp->expr = np; 235 dp->next = NULL; 236 237 if (ip->head == NULL) { 238 ip->head = ip->tail = dp; 239 } else { 240 ip->tail->next = dp; 241 ip->tail = dp; 242 } 243 244 if (ip->pos+1 > ip->max) 245 ip->max = ip->pos+1; 246 } 247 248 static Node * 249 initlist_helper(Type *tp) 250 { 251 Init in; 252 Node *np; 253 Type *curtp, *btp; 254 int braces, scalar, toomany, outbound; 255 long long nelem = tp->n.elem; 256 257 braces = scalar = toomany = 0; 258 259 if (accept('{')) 260 braces = 1; 261 262 if (yytoken == STRING && tp->op == ARY) { 263 btp = tp->type; 264 if (btp == chartype || btp == uchartype || btp == schartype) { 265 np = str2ary(tp); 266 if (braces) 267 expect('}'); 268 return np; 269 } 270 } 271 272 init(&in); 273 for (;;) { 274 curtp = inttype; 275 switch (yytoken) { 276 case '[': 277 in.pos = arydesig(tp, &in); 278 curtp = tp->type; 279 goto desig_list; 280 case '.': 281 in.pos = fielddesig(tp, &in); 282 if (in.pos >= 0 && in.pos < nelem) 283 curtp = tp->p.fields[in.pos]->type; 284 desig_list: 285 if (yytoken == '[' || yytoken == '.') { 286 np = initlist(curtp); 287 goto new_desig; 288 } 289 expect('='); 290 default: 291 outbound = 0; 292 293 switch (tp->op) { 294 case ARY: 295 curtp = tp->type; 296 if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem) 297 break; 298 if (!toomany) 299 warn("excess elements in array initializer"); 300 toomany = 1; 301 outbound = 1; 302 break; 303 case UNION: 304 case STRUCT: 305 if (in.pos < nelem) { 306 curtp = tp->p.fields[in.pos]->type; 307 break; 308 } 309 if (!toomany) 310 warn("excess elements in struct initializer"); 311 toomany = 1; 312 outbound = 1; 313 break; 314 default: 315 curtp = tp; 316 if (!scalar) 317 warn("braces around scalar initializer"); 318 scalar = 1; 319 if (in.pos == 0) 320 break; 321 if (!toomany) 322 warn("excess elements in scalar initializer"); 323 toomany = 1; 324 outbound = 1; 325 break; 326 } 327 np = initialize(curtp, INLIST); 328 if (outbound) { 329 freetree(np); 330 np = NULL; 331 } 332 } 333 334 new_desig: 335 if (np) 336 newdesig(&in, np); 337 if (++in.pos == 0) 338 errorp("compound literal too big"); 339 if (nelem == in.pos && !braces) 340 break; 341 if (!accept(',')) 342 break; 343 if (yytoken == '}') 344 break; 345 } 346 347 if (braces) 348 expect('}'); 349 350 351 if (tp->op == ARY && !(tp->prop & TDEFINED)) { 352 tp->n.elem = in.max; 353 deftype(tp); 354 } 355 if (in.max == 0) { 356 errorp("empty braced initializer"); 357 return constnode(zero); 358 } 359 360 return mkcompound(&in, tp); 361 } 362 363 static Node * 364 initlist(Type *tp) 365 { 366 Node *np; 367 static int depth; 368 369 if (depth == NR_SUBTYPE) 370 error("too many nested initializers"); 371 372 ++depth; 373 np = initlist_helper(tp); 374 --depth; 375 376 return np; 377 } 378 379 static void 380 autofield(Symbol *sym, Node *np, Type *tp, unsigned long long *addr) 381 { 382 int align; 383 Node *aux; 384 unsigned long long na; 385 386 align = tp->align - 1; 387 na = *addr; 388 na = (na + align) & ~align; 389 *addr = na; 390 391 aux = node(OADDR, pvoidtype, varnode(sym), NULL); 392 aux = node(OADD, pvoidtype, aux, addrnode(na)); 393 aux = node(OPTR, tp, aux, NULL); 394 aux = node(OASSIGN, tp, aux, np); 395 396 emit(OEXPR, aux); 397 *addr += tp->size; 398 } 399 400 static void 401 autocomp(Symbol *sym, Node *np, Type *tp, unsigned long long *addr) 402 { 403 Type *p; 404 Node *aux; 405 Symbol *init; 406 unsigned long long n; 407 408 if (!np) { 409 init = NULL; 410 } else { 411 if (!np->sym) 412 goto expression; 413 init = np->sym; 414 if ((init->flags & SINITLST) == 0) 415 goto expression; 416 } 417 418 switch (tp->op) { 419 case PTR: 420 case INT: 421 case ENUM: 422 aux = init ? *init->u.init : zeronode(tp); 423 autofield(sym, aux, aux->type, addr); 424 break; 425 case UNION: 426 aux = (init) ? init->u.init[0] : NULL; 427 p = (aux) ? aux->type : tp->p.fields[0]->type; 428 autocomp(sym, aux, p, addr); 429 break; 430 case STRUCT: 431 case ARY: 432 if (np && (np->flags & NCONST) != 0) { 433 Symbol *hidden = newsym(NS_IDEN, NULL); 434 hidden->id = newid(); 435 hidden->type = init->type; 436 hidden->flags |= SLOCAL | SHASINIT; 437 emit(ODECL, hidden); 438 emit(OINIT, np); 439 np = varnode(hidden); 440 goto expression; 441 } 442 for (n = 0; n < tp->n.elem; ++n) { 443 aux = (init) ? init->u.init[n] : NULL; 444 p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type; 445 autocomp(sym, aux, p, addr); 446 } 447 break; 448 default: 449 abort(); 450 } 451 452 if (init) { 453 free(init->u.init); 454 init->u.init = NULL; 455 } 456 freetree(np); 457 return; 458 459 expression: 460 autofield(sym, np, tp, addr); 461 } 462 463 static void 464 emitstrings(Node *np) 465 { 466 unsigned f; 467 Symbol *sym; 468 long long i, n; 469 470 if (!np) 471 return; 472 473 if (np->op == OSYM) { 474 sym = np->sym; 475 f = sym->flags & (SSTRING|SRSTRING|SEMITTED|SINITLST); 476 if (f == SSTRING || f == SRSTRING) { 477 sym->flags |= SHASINIT; 478 emit(ODECL, sym); 479 emit(OINIT, constnode(sym)); 480 } else if (f == SINITLST) { 481 n = (np->type->op == UNION) ? 1 : np->type->n.elem; 482 for (i = 0; i < n; ++i) 483 emitstrings(sym->u.init[i]); 484 } 485 } 486 487 emitstrings(np->left); 488 emitstrings(np->right); 489 } 490 491 static void 492 autoinit(Symbol *sym, Node *np) 493 { 494 unsigned long long a; 495 Symbol *hidden; 496 Type *tp = np->type; 497 498 repeat: 499 switch (tp->op) { 500 case UNION: 501 np = np->sym->u.init[0]; 502 tp = np->type; 503 goto repeat; 504 case ARY: 505 if (np->op == OADDR && np->sym->flags & SSTRING) 506 goto hidden_data; 507 case STRUCT: 508 if (np->op != OSYM || (np->sym->flags & SINITLST) == 0) 509 goto expr; 510 hidden_data: 511 if (!(np->flags & NCONST)) { 512 a = 0; 513 emitstrings(np); 514 emit(ODECL, sym); 515 autocomp(sym, np, np->type, &a); 516 break; 517 } 518 hidden = newsym(NS_IDEN, NULL); 519 hidden->id = newid(); 520 hidden->type = sym->type; 521 hidden->flags |= SLOCAL | SHASINIT; 522 emit(ODECL, hidden); 523 emit(OINIT, np); 524 np = varnode(hidden); 525 default: 526 expr: 527 emitstrings(np); 528 emit(ODECL, sym); 529 np = node(OASSIGN, tp, varnode(sym), np); 530 emit(OEXPR, np); 531 break; 532 } 533 } 534 535 void 536 initializer(Symbol *sym) 537 { 538 Node *np; 539 Type *tp = sym->type; 540 int flags = sym->flags; 541 542 if (tp->op == FTN) { 543 errorp("function '%s' initialized like a variable", 544 sym->name); 545 tp = inttype; 546 } 547 np = initialize(tp, NOLIST); 548 549 if (flags & SDEFINED) { 550 errorp("redeclaration of '%s'", sym->name); 551 } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) { 552 if ((np->flags & NCONST) == 0) { 553 errorp("initializer element is not constant"); 554 return; 555 } 556 sym->flags |= SHASINIT; 557 sym->flags &= ~SEMITTED; 558 emit(ODECL, sym); 559 emit(OINIT, np); 560 sym->flags |= SDEFINED; 561 } else if ((flags & (SEXTERN|STYPEDEF)) != 0) { 562 errorp("'%s' has both '%s' and initializer", 563 sym->name, (flags&SEXTERN) ? "extern" : "typedef"); 564 } else { 565 autoinit(sym, np); 566 } 567 }