scc

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