scc

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

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 }