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