scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

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 }