scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

init.c (6883B)


      1 static char sccsid[] = "@(#) ./cc1/init.c";
      2 #include <stdint.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 
      6 #include <cstd.h>
      7 #include "../inc/scc.h"
      8 #include "cc1.h"
      9 
     10 
     11 typedef struct init Init;
     12 
     13 struct designator {
     14 	TINT pos;
     15 	Node *expr;
     16 	struct designator *next;
     17 };
     18 
     19 struct init {
     20 	TUINT pos;
     21 	TUINT max;
     22 	struct designator *tail;
     23 	struct designator *head;
     24 };
     25 
     26 static TINT
     27 arydesig(Type *tp, Init *ip)
     28 {
     29 	TINT npos;
     30 	Node *np;
     31 
     32 	if (tp->op != ARY)
     33 		errorp("array index in non-array initializer");
     34 	next();
     35 	np = constexpr();
     36 	npos = np->sym->u.i;
     37 	if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) {
     38 		errorp("array index in initializer exceeds array bounds");
     39 		npos = 0;
     40 	}
     41 	freetree(np);
     42 	expect(']');
     43 	return npos;
     44 }
     45 
     46 static TINT
     47 fielddesig(Type *tp, Init *ip)
     48 {
     49 	int ons;
     50 	Symbol *sym, **p;
     51 
     52 	if (!(tp->prop & TAGGREG))
     53 		errorp("field name not in record or union initializer");
     54 	ons = namespace;
     55 	namespace = tp->ns;
     56 	next();
     57 	namespace = ons;
     58 	if (yytoken != IDEN)
     59 		unexpected();
     60 	sym = yylval.sym;
     61 	next();
     62 	if ((sym->flags & SDECLARED) == 0) {
     63 		errorp("unknown field '%s' specified in initializer",
     64 		      sym->name);
     65 		return 0;
     66 	}
     67 	for (p = tp->p.fields; *p != sym; ++p)
     68 		/* nothing */;
     69 	return p - tp->p.fields;
     70 }
     71 
     72 static Init *
     73 init(Init *ip)
     74 {
     75 	ip->tail = ip->head = NULL;
     76 	ip->pos = ip->max = 0;
     77 	return ip;
     78 }
     79 
     80 static Node *
     81 str2ary(Type *tp)
     82 {
     83 	Node *np;
     84 	Type *btp = tp->type;;
     85 	Symbol *sym;
     86 	size_t len;
     87 	char *s;
     88 
     89 	np = assign();
     90 	sym = np->left->sym;
     91 	if (btp != chartype && btp != uchartype && btp != schartype) {
     92 		errorp("array of inappropriate type initialized from string constant");
     93 		return constnode(zero);
     94 	}
     95 
     96 	len = sym->type->n.elem-1;
     97 	if (!(tp->prop & TDEFINED)) {
     98 		tp->n.elem = len+1;
     99 		deftype(tp);
    100 	} else if (tp->n.elem < len) {
    101 		warn("initializer-string for array of chars is too long");
    102 	}
    103 
    104 	len = tp->n.elem;
    105 	s = sym->u.s;
    106 	sym = newstring(NULL, len);
    107 	strncpy(sym->u.s, s, len);
    108 	np->sym = sym;
    109 	np->type = sym->type;
    110 
    111 	return np;
    112 }
    113 
    114 static Node *
    115 initialize(Type *tp)
    116 {
    117 	Node *np;
    118 	Symbol *sym;
    119 
    120 	if (tp->op == ARY && yytoken == STRING)
    121 		return str2ary(tp);
    122 
    123 	if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY)
    124 		return initlist(tp);
    125 
    126 	np = assign();
    127 	if (eqtype(tp, np->type, 1))
    128 		return np;
    129 
    130 	np = convert(decay(np), tp, 0);
    131 	if (!np) {
    132 		errorp("incorrect initializer");
    133 		return constnode(zero);
    134 	}
    135 
    136 	return simplify(np);
    137 }
    138 
    139 static Node *
    140 mkcompound(Init *ip, Type *tp)
    141 {
    142 	Node **v, **p;
    143 	size_t n;
    144 	struct designator *dp, *next;
    145 	Symbol *sym;
    146 
    147 	if (tp->op == UNION) {
    148 		Node *np = NULL;
    149 
    150 		v = xmalloc(sizeof(*v));
    151 		for (dp = ip->head; dp; dp = next) {
    152 			freetree(np);
    153 			np = dp->expr;
    154 			next = dp->next;
    155 			free(dp);
    156 		}
    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 				*p = dp->expr;
    173 				next = dp->next;
    174 				free(dp);
    175 			}
    176 		}
    177 	}
    178 
    179 	sym = newsym(NS_IDEN, NULL);
    180 	sym->u.init = v;
    181 	sym->type = tp;
    182 	sym->flags |= SINITLST;
    183 
    184 	return constnode(sym);
    185 }
    186 
    187 static void
    188 newdesig(Init *ip, Node *np)
    189 {
    190 	struct designator *dp;
    191 
    192 	dp = xmalloc(sizeof(*dp));
    193 	dp->pos = ip->pos;
    194 	dp->expr = np;
    195 	dp->next = NULL;
    196 
    197 	if (ip->head == NULL) {
    198 		ip->head = ip->tail = dp;
    199 	} else {
    200 		ip->tail->next = dp;
    201 		ip->tail = dp;
    202 	}
    203 
    204 	if (ip->pos+1 > ip->max)
    205 		ip->max = ip->pos+1;
    206 }
    207 
    208 Node *
    209 initlist(Type *tp)
    210 {
    211 	Init in;
    212 	Node *np;
    213 	Type *curtp;
    214 	int braces, scalar, toomany, outbound;
    215 	TINT nelem = tp->n.elem;
    216 	static int depth;
    217 
    218 	if (depth == NR_SUBTYPE)
    219 		error("too many nested initializers");
    220 	++depth;
    221 	init(&in);
    222 	braces = scalar = toomany = 0;
    223 
    224 	if (accept('{'))
    225 		braces = 1;
    226 
    227 	do {
    228 		curtp = inttype;
    229 		switch (yytoken) {
    230 		case '[':
    231 			in.pos = arydesig(tp, &in);
    232 			curtp = tp->type;
    233 			goto desig_list;
    234 		case '.':
    235 			in.pos = fielddesig(tp, &in);
    236 			if (in.pos < nelem)
    237 				curtp = tp->p.fields[in.pos]->type;
    238 		desig_list:
    239 			if (yytoken == '[' || yytoken == '.') {
    240 				np = initlist(curtp);
    241 				goto new_desig;
    242 			}
    243 			expect('=');
    244 		default:
    245 			outbound = 0;
    246 
    247 			switch (tp->op) {
    248 			case ARY:
    249 				curtp = tp->type;
    250 				if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem)
    251 					break;
    252 				if (!toomany)
    253 					warn("excess elements in array initializer");
    254 				toomany = 1;
    255 				outbound = 1;
    256 				break;
    257 			case UNION:
    258 			case STRUCT:
    259 				if (in.pos < nelem) {
    260 					curtp = tp->p.fields[in.pos]->type;
    261 					break;
    262 				}
    263 				if (!toomany)
    264 					warn("excess elements in struct initializer");
    265 				toomany = 1;
    266 				outbound = 1;
    267 				break;
    268 			default:
    269 				curtp = tp;
    270 				if (!scalar)
    271 					warn("braces around scalar initializer");
    272 				scalar = 1;
    273 				if (in.pos == 0)
    274 					break;
    275 				if (!toomany)
    276 					warn("excess elements in scalar initializer");
    277 				toomany = 1;
    278 				outbound = 1;
    279 				break;
    280 			}
    281 			np = initialize(curtp);
    282 			if (outbound) {
    283 				freetree(np);
    284 				np = NULL;
    285 			}
    286 		}
    287 
    288 new_desig:
    289 		if (np)
    290 			newdesig(&in, np);
    291 		if (++in.pos == 0)
    292 			errorp("compound literal too big");
    293 		if (nelem == in.pos && !braces)
    294 			break;
    295 	} while (accept(','));
    296 
    297 	if (braces)
    298 		expect('}');
    299 
    300 
    301 	if (tp->op == ARY && !(tp->prop & TDEFINED)) {
    302 		tp->n.elem = in.max;
    303 		deftype(tp);
    304 	}
    305 	if (in.max == 0) {
    306 		errorp("empty braced initializer");
    307 		return constnode(zero);
    308 	}
    309 
    310 	return mkcompound(&in, tp);
    311 }
    312 
    313 static void
    314 autoinit(Symbol *sym, Node *np)
    315 {
    316 	Symbol *hidden;
    317 	Type *tp = sym->type;
    318 	size_t n; /* FIXME: It should be SIZET */
    319 
    320 repeat:
    321 	switch (tp->op) {
    322 	case UNION:
    323 		np = np->sym->u.init[0];
    324 		tp = np->type;
    325 		goto repeat;
    326 	case ARY:
    327 	case STRUCT:
    328 		if (!(np->flags & NCONST))
    329 			abort(); /* TODO */
    330 		hidden = newsym(NS_IDEN, NULL);
    331 		hidden->type = sym->type;
    332 		hidden->flags |= SLOCAL | SHASINIT;
    333 		emit(ODECL, hidden);
    334 		emit(OINIT, np);
    335 		emit(ODECL, sym);
    336 		emit(OEXPR,
    337 		     node(OASSIGN, tp, varnode(sym), varnode(hidden)));
    338 		break;
    339 	default:
    340 		emit(ODECL, sym);
    341 		np = node(OASSIGN, tp, varnode(sym), np);
    342 		emit(OEXPR, np);
    343 		break;
    344 	}
    345 }
    346 
    347 void
    348 initializer(Symbol *sym, Type *tp)
    349 {
    350 	Node *np;
    351 	int flags = sym->flags;
    352 
    353 	if (tp->op == FTN) {
    354 		errorp("function '%s' initialized like a variable",
    355 		       sym->name);
    356 		tp = inttype;
    357 	}
    358 	np = initialize(tp);
    359 
    360 	if (flags & SDEFINED) {
    361 		errorp("redeclaration of '%s'", sym->name);
    362 	} else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
    363 		if (!(np->flags & NCONST)) {
    364 			errorp("initializer element is not constant");
    365 			return;
    366 		}
    367 		sym->flags |= SHASINIT;
    368 		sym->flags &= ~SEMITTED;
    369 		emit(ODECL, sym);
    370 		emit(OINIT, np);
    371 		sym->flags |= SDEFINED;
    372 	} else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
    373 		errorp("'%s' has both '%s' and initializer",
    374 		       sym->name, (flags&SEXTERN) ? "extern" : "typedef");
    375 	} else {
    376 		autoinit(sym, np);
    377 	}
    378 }