init.c (7136B)
1 #include <stdint.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #include <scc/cstd.h> 6 #include <scc/scc.h> 7 #include "cc1.h" 8 9 10 typedef struct init Init; 11 12 struct designator { 13 TINT pos; 14 Node *expr; 15 struct designator *next; 16 }; 17 18 struct init { 19 TUINT pos; 20 TUINT max; 21 struct designator *tail; 22 struct designator *head; 23 }; 24 25 static TINT 26 arydesig(Type *tp, Init *ip) 27 { 28 TINT npos; 29 Node *np; 30 31 if (tp->op != ARY) 32 errorp("array index in non-array initializer"); 33 next(); 34 np = constexpr(); 35 npos = np->sym->u.i; 36 if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) { 37 errorp("array index in initializer exceeds array bounds"); 38 npos = 0; 39 } 40 freetree(np); 41 expect(']'); 42 return npos; 43 } 44 45 static TINT 46 fielddesig(Type *tp, Init *ip) 47 { 48 int ons; 49 Symbol *sym, **p; 50 51 if (!(tp->prop & TAGGREG)) 52 errorp("field name not in record or union initializer"); 53 ons = namespace; 54 namespace = tp->ns; 55 next(); 56 namespace = ons; 57 if (yytoken != IDEN) 58 unexpected(); 59 sym = yylval.sym; 60 next(); 61 if ((sym->flags & SDECLARED) == 0) { 62 errorp("unknown field '%s' specified in initializer", 63 sym->name); 64 return -1; 65 } 66 for (p = tp->p.fields; *p != sym; ++p) 67 ; 68 return p - tp->p.fields; 69 } 70 71 static Init * 72 init(Init *ip) 73 { 74 ip->tail = ip->head = NULL; 75 ip->pos = ip->max = 0; 76 return ip; 77 } 78 79 static Node * 80 str2ary(Type *tp) 81 { 82 Node *np; 83 Type *btp = tp->type; 84 Symbol *sym; 85 size_t len; 86 char *s; 87 88 np = assign(); 89 sym = np->left->sym; 90 if (btp != chartype && btp != uchartype && btp != schartype) { 91 errorp("array of inappropriate type initialized from string constant"); 92 return constnode(zero); 93 } 94 95 len = sym->type->n.elem-1; 96 if (!(tp->prop & TDEFINED)) { 97 tp->n.elem = len+1; 98 deftype(tp); 99 } else if (tp->n.elem < len) { 100 warn("initializer-string for array of chars is too long"); 101 } 102 103 len = tp->n.elem; 104 s = sym->u.s; 105 sym = newstring(NULL, len); 106 strncpy(sym->u.s, s, len); 107 np->sym = sym; 108 np->type = sym->type; 109 110 return np; 111 } 112 113 static Node * 114 initialize(Type *tp) 115 { 116 Node *np; 117 Symbol *sym; 118 119 if (tp->op == ARY && yytoken == STRING) 120 return str2ary(tp); 121 122 if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY) 123 return initlist(tp); 124 125 np = assign(); 126 if (!eqtype(tp, np->type, EQUIV)) { 127 np = convert(decay(np), tp, 0); 128 if (!np) { 129 errorp("incorrect initializer"); 130 return constnode(zero); 131 } 132 } 133 134 return simplify(np); 135 } 136 137 static Node * 138 mkcompound(Init *ip, Type *tp) 139 { 140 Node **v, **p, *np; 141 size_t n; 142 struct designator *dp, *next; 143 Symbol *sym; 144 int isconst = 1; 145 146 if (tp->op == UNION) { 147 np = NULL; 148 v = xmalloc(sizeof(*v)); 149 for (dp = ip->head; dp; dp = next) { 150 freetree(np); 151 np = dp->expr; 152 next = dp->next; 153 free(dp); 154 } 155 if ((np->flags & NCONST) == 0) 156 isconst = 0; 157 *v = np; 158 } else { 159 n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max; 160 if (n == 0) { 161 v = NULL; 162 } else if (n > SIZE_MAX / sizeof(*v)) { 163 errorp("compound literal too big"); 164 return constnode(zero); 165 } else { 166 n *= sizeof(*v); 167 v = memset(xmalloc(n), 0, n); 168 169 for (dp = ip->head; dp; dp = next) { 170 p = &v[dp->pos]; 171 freetree(*p); 172 np = dp->expr; 173 *p = np; 174 if ((np->flags & NCONST) == 0) 175 isconst = 0; 176 next = dp->next; 177 free(dp); 178 } 179 } 180 } 181 182 sym = newsym(NS_IDEN, NULL); 183 sym->u.init = v; 184 sym->type = tp; 185 sym->flags |= SINITLST; 186 187 return (isconst ? constnode : varnode)(sym); 188 } 189 190 static void 191 newdesig(Init *ip, Node *np) 192 { 193 struct designator *dp; 194 195 dp = xmalloc(sizeof(*dp)); 196 dp->pos = ip->pos; 197 dp->expr = np; 198 dp->next = NULL; 199 200 if (ip->head == NULL) { 201 ip->head = ip->tail = dp; 202 } else { 203 ip->tail->next = dp; 204 ip->tail = dp; 205 } 206 207 if (ip->pos+1 > ip->max) 208 ip->max = ip->pos+1; 209 } 210 211 static Node * 212 initlist_helper(Type *tp) 213 { 214 Init in; 215 Node *np; 216 Type *curtp; 217 int braces, scalar, toomany, outbound; 218 TINT nelem = tp->n.elem; 219 220 init(&in); 221 braces = scalar = toomany = 0; 222 223 if (accept('{')) 224 braces = 1; 225 226 for (;;) { 227 curtp = inttype; 228 switch (yytoken) { 229 case '[': 230 in.pos = arydesig(tp, &in); 231 curtp = tp->type; 232 goto desig_list; 233 case '.': 234 in.pos = fielddesig(tp, &in); 235 if (in.pos >= 0 && in.pos < nelem) 236 curtp = tp->p.fields[in.pos]->type; 237 desig_list: 238 if (yytoken == '[' || yytoken == '.') { 239 np = initlist(curtp); 240 goto new_desig; 241 } 242 expect('='); 243 default: 244 outbound = 0; 245 246 switch (tp->op) { 247 case ARY: 248 curtp = tp->type; 249 if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem) 250 break; 251 if (!toomany) 252 warn("excess elements in array initializer"); 253 toomany = 1; 254 outbound = 1; 255 break; 256 case UNION: 257 case STRUCT: 258 if (in.pos < nelem) { 259 curtp = tp->p.fields[in.pos]->type; 260 break; 261 } 262 if (!toomany) 263 warn("excess elements in struct initializer"); 264 toomany = 1; 265 outbound = 1; 266 break; 267 default: 268 curtp = tp; 269 if (!scalar) 270 warn("braces around scalar initializer"); 271 scalar = 1; 272 if (in.pos == 0) 273 break; 274 if (!toomany) 275 warn("excess elements in scalar initializer"); 276 toomany = 1; 277 outbound = 1; 278 break; 279 } 280 np = initialize(curtp); 281 if (outbound) { 282 freetree(np); 283 np = NULL; 284 } 285 } 286 287 new_desig: 288 if (np) 289 newdesig(&in, np); 290 if (++in.pos == 0) 291 errorp("compound literal too big"); 292 if (nelem == in.pos && !braces) 293 break; 294 if (!accept(',')) 295 break; 296 if (yytoken == '}') 297 break; 298 } 299 300 if (braces) 301 expect('}'); 302 303 304 if (tp->op == ARY && !(tp->prop & TDEFINED)) { 305 tp->n.elem = in.max; 306 deftype(tp); 307 } 308 if (in.max == 0) { 309 errorp("empty braced initializer"); 310 return constnode(zero); 311 } 312 313 return mkcompound(&in, tp); 314 } 315 316 Node * 317 initlist(Type *tp) 318 { 319 Node *np; 320 static int depth; 321 322 if (depth == NR_SUBTYPE) 323 error("too many nested initializers"); 324 325 ++depth; 326 np = initlist_helper(tp); 327 --depth; 328 329 return np; 330 } 331 332 static void 333 autoinit(Symbol *sym, Node *np) 334 { 335 Symbol *hidden; 336 Type *tp = sym->type; 337 338 repeat: 339 switch (tp->op) { 340 case UNION: 341 np = np->sym->u.init[0]; 342 tp = np->type; 343 goto repeat; 344 case ARY: 345 case STRUCT: 346 if (!(np->flags & NCONST)) 347 abort(); /* TODO */ 348 hidden = newsym(NS_IDEN, NULL); 349 hidden->id = newid(); 350 hidden->type = sym->type; 351 hidden->flags |= SLOCAL | SHASINIT; 352 emit(ODECL, hidden); 353 emit(OINIT, np); 354 emit(ODECL, sym); 355 emit(OEXPR, 356 node(OASSIGN, tp, varnode(sym), varnode(hidden))); 357 break; 358 default: 359 emit(ODECL, sym); 360 np = node(OASSIGN, tp, varnode(sym), np); 361 emit(OEXPR, np); 362 break; 363 } 364 } 365 366 void 367 initializer(Symbol *sym, Type *tp) 368 { 369 Node *np; 370 int flags = sym->flags; 371 372 if (tp->op == FTN) { 373 errorp("function '%s' initialized like a variable", 374 sym->name); 375 tp = inttype; 376 } 377 np = initialize(tp); 378 379 if (flags & SDEFINED) { 380 errorp("redeclaration of '%s'", sym->name); 381 } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) { 382 if ((np->flags & NCONST) == 0) { 383 errorp("initializer element is not constant"); 384 return; 385 } 386 sym->flags |= SHASINIT; 387 sym->flags &= ~SEMITTED; 388 emit(ODECL, sym); 389 emit(OINIT, np); 390 sym->flags |= SDEFINED; 391 } else if ((flags & (SEXTERN|STYPEDEF)) != 0) { 392 errorp("'%s' has both '%s' and initializer", 393 sym->name, (flags&SEXTERN) ? "extern" : "typedef"); 394 } else { 395 autoinit(sym, np); 396 } 397 }