scc

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

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 }