scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 14typedef struct init Init;
 15
 16struct designator {
 17	long long pos;
 18	Node *expr;
 19	struct designator *next;
 20};
 21
 22struct init {
 23	unsigned long long pos;
 24	unsigned long long max;
 25	struct designator *tail;
 26	struct designator *head;
 27};
 28
 29int disstring;
 30
 31static long long
 32arydesig(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
 58static long long
 59fielddesig(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
 84static Init *
 85init(Init *ip)
 86{
 87	ip->tail = ip->head = NULL;
 88	ip->pos = ip->max = 0;
 89	return ip;
 90}
 91
 92static Node *
 93str2ary(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
143wrong:
144	errorp("array of inappropriate type initialized from string constant");
145	return constnode(zero);
146}
147
148static Node *initlist(Type *);
149
150static Node *
151initialize(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
174static Node *
175mkcompound(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
227static void
228newdesig(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
248static Node *
249initlist_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
334new_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
363static Node *
364initlist(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
379static void
380autofield(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
400static void
401autocomp(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
459expression:
460	autofield(sym, np, tp, addr);
461}
462
463static void
464emitstrings(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
491static void
492autoinit(Symbol *sym, Node *np)
493{
494	unsigned long long a;
495	Symbol *hidden;
496	Type *tp = np->type;
497
498repeat:
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
535void
536initializer(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}