scc

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

init.c (6827B)


      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 0;
     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, 1))
    127 		return np;
    128 
    129 	np = convert(decay(np), tp, 0);
    130 	if (!np) {
    131 		errorp("incorrect initializer");
    132 		return constnode(zero);
    133 	}
    134 
    135 	return simplify(np);
    136 }
    137 
    138 static Node *
    139 mkcompound(Init *ip, Type *tp)
    140 {
    141 	Node **v, **p;
    142 	size_t n;
    143 	struct designator *dp, *next;
    144 	Symbol *sym;
    145 
    146 	if (tp->op == UNION) {
    147 		Node *np = NULL;
    148 
    149 		v = xmalloc(sizeof(*v));
    150 		for (dp = ip->head; dp; dp = next) {
    151 			freetree(np);
    152 			np = dp->expr;
    153 			next = dp->next;
    154 			free(dp);
    155 		}
    156 		*v = np;
    157 	} else {
    158 		n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max;
    159 		if (n == 0) {
    160 			v = NULL;
    161 		} else if (n > SIZE_MAX / sizeof(*v)) {
    162 			errorp("compound literal too big");
    163 			return constnode(zero);
    164 		} else {
    165 			n *= sizeof(*v);
    166 			v = memset(xmalloc(n), 0, n);
    167 
    168 			for (dp = ip->head; dp; dp = next) {
    169 				p = &v[dp->pos];
    170 				freetree(*p);
    171 				*p = dp->expr;
    172 				next = dp->next;
    173 				free(dp);
    174 			}
    175 		}
    176 	}
    177 
    178 	sym = newsym(NS_IDEN, NULL);
    179 	sym->u.init = v;
    180 	sym->type = tp;
    181 	sym->flags |= SINITLST;
    182 
    183 	return constnode(sym);
    184 }
    185 
    186 static void
    187 newdesig(Init *ip, Node *np)
    188 {
    189 	struct designator *dp;
    190 
    191 	dp = xmalloc(sizeof(*dp));
    192 	dp->pos = ip->pos;
    193 	dp->expr = np;
    194 	dp->next = NULL;
    195 
    196 	if (ip->head == NULL) {
    197 		ip->head = ip->tail = dp;
    198 	} else {
    199 		ip->tail->next = dp;
    200 		ip->tail = dp;
    201 	}
    202 
    203 	if (ip->pos+1 > ip->max)
    204 		ip->max = ip->pos+1;
    205 }
    206 
    207 Node *
    208 initlist(Type *tp)
    209 {
    210 	Init in;
    211 	Node *np;
    212 	Type *curtp;
    213 	int braces, scalar, toomany, outbound;
    214 	TINT nelem = tp->n.elem;
    215 	static int depth;
    216 
    217 	if (depth == NR_SUBTYPE)
    218 		error("too many nested initializers");
    219 	++depth;
    220 	init(&in);
    221 	braces = scalar = toomany = 0;
    222 
    223 	if (accept('{'))
    224 		braces = 1;
    225 
    226 	do {
    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 < 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 	} while (accept(','));
    295 
    296 	if (braces)
    297 		expect('}');
    298 
    299 
    300 	if (tp->op == ARY && !(tp->prop & TDEFINED)) {
    301 		tp->n.elem = in.max;
    302 		deftype(tp);
    303 	}
    304 	if (in.max == 0) {
    305 		errorp("empty braced initializer");
    306 		return constnode(zero);
    307 	}
    308 
    309 	return mkcompound(&in, tp);
    310 }
    311 
    312 static void
    313 autoinit(Symbol *sym, Node *np)
    314 {
    315 	Symbol *hidden;
    316 	Type *tp = sym->type;
    317 	size_t n; /* FIXME: It should be SIZET */
    318 
    319 repeat:
    320 	switch (tp->op) {
    321 	case UNION:
    322 		np = np->sym->u.init[0];
    323 		tp = np->type;
    324 		goto repeat;
    325 	case ARY:
    326 	case STRUCT:
    327 		if (!(np->flags & NCONST))
    328 			abort(); /* TODO */
    329 		hidden = newsym(NS_IDEN, NULL);
    330 		hidden->type = sym->type;
    331 		hidden->flags |= SLOCAL | SHASINIT;
    332 		emit(ODECL, hidden);
    333 		emit(OINIT, np);
    334 		emit(ODECL, sym);
    335 		emit(OEXPR,
    336 		     node(OASSIGN, tp, varnode(sym), varnode(hidden)));
    337 		break;
    338 	default:
    339 		emit(ODECL, sym);
    340 		np = node(OASSIGN, tp, varnode(sym), np);
    341 		emit(OEXPR, np);
    342 		break;
    343 	}
    344 }
    345 
    346 void
    347 initializer(Symbol *sym, Type *tp)
    348 {
    349 	Node *np;
    350 	int flags = sym->flags;
    351 
    352 	if (tp->op == FTN) {
    353 		errorp("function '%s' initialized like a variable",
    354 		       sym->name);
    355 		tp = inttype;
    356 	}
    357 	np = initialize(tp);
    358 
    359 	if (flags & SDEFINED) {
    360 		errorp("redeclaration of '%s'", sym->name);
    361 	} else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
    362 		if (!(np->flags & NCONST)) {
    363 			errorp("initializer element is not constant");
    364 			return;
    365 		}
    366 		sym->flags |= SHASINIT;
    367 		sym->flags &= ~SEMITTED;
    368 		emit(ODECL, sym);
    369 		emit(OINIT, np);
    370 		sym->flags |= SDEFINED;
    371 	} else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
    372 		errorp("'%s' has both '%s' and initializer",
    373 		       sym->name, (flags&SEXTERN) ? "extern" : "typedef");
    374 	} else {
    375 		autoinit(sym, np);
    376 	}
    377 }