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