shithub: scc

Download patch

ref: 43a3b37a514e390199668bab42c3451901de5917
parent: 8f5f61842eec2f1553ddbc90bf454600168f0718
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Jan 18 10:20:50 EST 2016

Emit compound initializers

At this point we are not emiting anything, but we have the full process
working. We have to create a function which could emit this kind of
constants.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -384,7 +384,7 @@
 extern TUINT ones(int nbytes);
 
 /* expr.c */
-extern Node *decay(Node *), *negate(Node *np), *assign(Node *np);;
+extern Node *decay(Node *), *negate(Node *np), *assign(void);;
 extern Node *convert(Node *np, Type *tp1, char iscast);
 extern Node *iconstexpr(void), *condexpr(void), *expr(void);
 extern bool isnodecmp(int op);
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -207,6 +207,8 @@
 		for (bp = sym->u.s; c = *bp; ++bp)
 			printf("%02X", c & 0xFF);
 		break;
+	case STRUCT:
+		return;
 	default:
 		/* TODO: Handle other kind of constants */
 		abort();
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -788,7 +788,7 @@
 
 	if (sym->token == IDEN && sym->type->op != FTN)
 		emit(ODECL, sym);
-	if (yytoken == '=')
+	if (accept('='))
 		initializer(sym, sym->type, -1);
 	if (!(sym->flags & (ISGLOBAL|ISEXTERN)) && tp->op != FTN)
 		sym->flags |= ISDEFINED;
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -512,9 +512,7 @@
 assignop(char op, Node *lp, Node *rp)
 {
 	if ((rp = convert(decay(rp), lp->type, 0)) == NULL) {
-		errorp((op == OINIT) ?
-		        "incorrect initiliazer" :
-		        "incompatible types when assigning");
+		errorp("incompatible types when assigning");
 		return lp;
 	}
 
@@ -657,7 +655,7 @@
 	toomany = 0;
 
 	do {
-		arg = decay(assign(NULL));
+		arg = decay(assign());
 		argtype = *targs;
 		if (argtype == ellipsistype) {
 			n = 0;
@@ -1006,21 +1004,15 @@
 }
 
 Node *
-assign(Node *np)
+assign(void)
 {
-	Node *(*fun)(char , Node *, Node *);
+	Node *np, *(*fun)(char , Node *, Node *);
 	char op;
 
-	if (np) {
-		op = OINIT;
-	} else {
-		op = OASSIGN;
-		np = ternary();
-	}
-
+	np = ternary();
 	for (;;) {
 		switch (yytoken) {
-		case '=': /* op = op; */;  fun = assignop;   break;
+		case '=':    op = OASSIGN; fun = assignop;   break;
 		case MUL_EQ: op = OA_MUL;  fun = arithmetic; break;
 		case DIV_EQ: op = OA_DIV;  fun = arithmetic; break;
 		case MOD_EQ: op = OA_MOD;  fun = integerop;  break;
@@ -1035,7 +1027,7 @@
 		}
 		chklvalue(np);
 		next();
-		np = (fun)(op, np, assign(NULL));
+		np = (fun)(op, np, assign());
 	}
 }
 
@@ -1073,9 +1065,9 @@
 {
 	Node *lp, *rp;
 
-	lp = assign(NULL);
+	lp = assign();
 	while (accept(',')) {
-		rp = assign(NULL);
+		rp = assign();
 		lp = node(OCOMMA, rp->type, lp, rp);
 	}
 
--- a/cc1/init.c
+++ b/cc1/init.c
@@ -78,11 +78,24 @@
 	return ip;
 }
 
+static Node *initlist(Type *tp);
+
 static Node *
-initlist(Symbol *sym, Type *tp)
+initialize(Type *tp)
 {
+	Node *np;
+
+	np = (accept('{')) ? initlist(tp) : assign();
+	if ((np = convert(decay(np), tp, 0)) == NULL)
+		errorp("incorrect initializer");
+	return np;
+}
+
+static Node *
+initlist(Type *tp)
+{
 	Init *ip;
-	Symbol *nsym;
+	Symbol *sym;
 	struct designator *dp;
 	int toomany = 0;
 	Type *newtp;
@@ -99,8 +112,8 @@
 		designation(ip);
 		switch (tp->op) {
 		case ARY:
-			newtp = tp->type;
-			if (!tp->defined || ip->pos < tp->n.elem)
+			newtp = sym->type;
+			if (!tp->defined || ip->pos <= tp->n.elem)
 				break;
 			if (!toomany)
 				warn("excess elements in array initializer");
@@ -107,11 +120,12 @@
 			toomany = 1;
 			break;
 		case STRUCT:
-			if (ip->pos < tp->n.elem) {
-				sym = tp->p.fields[ip->pos];
+			if (ip->pos <= tp->n.elem) {
+				sym = tp->p.fields[ip->pos-1];
 				newtp = sym->type;
 				break;
 			}
+			newtp = inttype;
 			if (!toomany)
 				warn("excess elements in struct initializer");
 			toomany = 1;
@@ -119,7 +133,7 @@
 		default:
 			newtp = tp;
 			warn("braces around scalar initializer");
-			if (ip->pos <= 0)
+			if (ip->pos == 1)
 				break;
 			if (!toomany)
 				warn("excess elements in scalar initializer");
@@ -128,8 +142,7 @@
 		}
 		dp = ip->head;
 		dp->pos = ip->pos;
-		/* TODO: pass the correct parameters to initlist */
-		dp->expr = (accept('{')) ? initlist(sym, tp) : assign(NULL);
+		dp->expr = initialize(newtp);
 
 		if (!accept(','))
 			break;
@@ -141,9 +154,10 @@
 		tp->n.elem = ip->pos;
 		tp->defined = 1;
 	}
-	nsym = newsym(NS_IDEN);
-	nsym->u.init = ip;
-	return constnode(nsym);
+	sym = newsym(NS_IDEN);
+	sym->u.init = ip;
+	sym->type = tp;
+	return constnode(sym);
 }
 
 void
@@ -155,14 +169,7 @@
 	if (tp->op == FTN)
 		errorp("function '%s' is initialized like a variable", sym->name);
 
-	switch (yytoken) {
-	case '{':
-		initlist(sym, tp);
-		return;
-	case '=':
-		np = assign(varnode(sym));
-		break;
-	}
+	np = node(OINIT, tp, varnode(sym), initialize(tp));
 
 	if (flags & ISDEFINED) {
 		errorp("redeclaration of '%s'", sym->name);