shithub: scc

Download patch

ref: 4730c12530c7db4e61d812e9f45d631d7bc1bdfe
parent: 1f34f795dd1fab4c3246623af6c8a095a5ffe634
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Sep 10 14:16:05 EDT 2015

Add initializer to static objects

Static objects cannot be initialized by assignations, so we need define
the initializer with other syntax.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -158,7 +158,8 @@
 	ISLOCAL    =     512,
 	ISEMITTED  =    1024,
 	ISDEFINED  =    2048,
-	ISSTRING   =    4096
+	ISSTRING   =    4096,
+	ISTYPEDEF =     8192
 };
 
 
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -16,7 +16,8 @@
             emitsymid(unsigned, void *),
             emittext(unsigned, void *),
             emitfun(unsigned, void *),
-            emitdcl(unsigned, void *);
+            emitdcl(unsigned, void *),
+            emitinit(unsigned, void *);
 
 char *optxt[] = {
 	[OADD] = "+",
@@ -39,7 +40,6 @@
 	[OBXOR]  = "^",
 	[OBOR] = "|",
 	[OASSIGN] = ":",
-	[OINIT] = ":",
 	[OA_MUL] = ":*",
 	[OA_DIV] = ":/",
 	[OA_MOD] = ":%",
@@ -92,7 +92,6 @@
 	[OBXOR]  = emitbin,
 	[OBOR] = emitbin,
 	[OASSIGN] = emitbin,
-	[OINIT] = emitbin,
 	[OA_MUL] = emitbin,
 	[OA_DIV] = emitbin,
 	[OA_MOD] = emitbin,
@@ -129,7 +128,8 @@
 	[OSWITCH] = emitswitch,
 	[OSWITCHT] = emitswitcht,
 	[OPAR] = emitbin,
-	[OCALL] = emitbin
+	[OCALL] = emitbin,
+	[OINIT] = emitinit
 };
 
 void
@@ -281,6 +281,18 @@
 	default:
 		abort();
 	}
+}
+
+static void
+emitinit(unsigned op, void *arg)
+{
+	Node *np = arg;
+
+	puts("(");
+	emitexp(OEXPR, np->right);
+	puts(")");
+	np->right = NULL;
+	freetree(np);
 }
 
 static void
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -661,6 +661,7 @@
 			flags |= (curctx == GLOBALCTX) ? ISPRIVATE : ISLOCAL;
 			break;
 		case TYPEDEF:
+			flags |= ISTYPEDEF;
 			sym->token = TYPEIDEN;
 			break;
 		}
@@ -668,8 +669,6 @@
 	}
 
 	/* TODO: disallow initializators in functions */
-	/* TODO: check if typedef has initializer */
-	/* TODO: check if the variable is extern and has initializer */
 	if (sym->token == IDEN && sym->type->op != FTN)
 		emit(ODECL, sym);
 	if (accept('='))
@@ -732,7 +731,7 @@
 		case TYPE:
 		case TQUALIFIER:
 		case SCLASS:
-			if (sym->token == TYPEIDEN)
+			if (sym->flags & ISTYPEDEF)
 				errorp("function definition declared 'typedef'");
 			if (sym->flags & ISDEFINED)
 				errorp("redefinition of '%s'", sym->name);
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -980,24 +980,46 @@
 
 /* TODO: check correctness of the initializator  */
 /* TODO: emit initializer */
+static void
+initlist(void)
+{
+	Node *np;
+
+	if (yytoken == '}')
+		return;
+
+	do {
+		if (accept('{'))
+			initlist();
+		assign();
+	} while (accept(','));
+
+	expect('}');
+}
+
 void
 initializer(Symbol *sym)
 {
 	Node *np;
+	int flags = sym->flags;
 
 	if (accept('{')) {
-		do {
-			if (yytoken == '}')
-				break;
-			initializer(sym);
-		} while (accept(','));
-
-		expect('}');
+		initlist();
 		return;
 	}
-	np = expr();
-	if ((sym->flags & ISLOCAL) == 0) {
-		emit(OEXPR, assignop(OINIT, varnode(sym), np));
-		return;
-	}
+	np = assignop(OINIT, varnode(sym), assign());
+
+	if ((flags & (ISLOCAL|ISPRIVATE|ISGLOBAL)) != 0) {
+		if (!np->right->constant)
+			errorp("initializer element is not constant");
+		emit(OINIT, np);
+	} else if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) {
+		errorp("'%s' has both '%s' and initializer",
+		       sym->name, (flags&ISEXTERN) ? "extern" : "typedef");
+	} else if (flags & ISFIELD) {
+		;
+	} else {
+		np->op = OASSIGN;
+		emit(OEXPR, np);
+	}	
 }
--