init.c - scc - simple c99 compiler
HTML git clone git://git.simple-cc.org/scc
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
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 }