commit 4730c12530c7db4e61d812e9f45d631d7bc1bdfe
parent 1f34f795dd1fab4c3246623af6c8a095a5ffe634
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 10 Sep 2015 18:16:05 +0200
Add initializer to static objects
Static objects cannot be initialized by assignations, so we need define
the initializer with other syntax.
Diffstat:
4 files changed, 54 insertions(+), 20 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -158,7 +158,8 @@ enum {
ISLOCAL = 512,
ISEMITTED = 1024,
ISDEFINED = 2048,
- ISSTRING = 4096
+ ISSTRING = 4096,
+ ISTYPEDEF = 8192
};
diff --git a/cc1/code.c b/cc1/code.c
@@ -16,7 +16,8 @@ static void emitbin(unsigned, void *),
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 @@ char *optxt[] = {
[OBXOR] = "^",
[OBOR] = "|",
[OASSIGN] = ":",
- [OINIT] = ":",
[OA_MUL] = ":*",
[OA_DIV] = ":/",
[OA_MOD] = ":%",
@@ -92,7 +92,6 @@ void (*opcode[])(unsigned, void *) = {
[OBXOR] = emitbin,
[OBOR] = emitbin,
[OASSIGN] = emitbin,
- [OINIT] = emitbin,
[OA_MUL] = emitbin,
[OA_DIV] = emitbin,
[OA_MOD] = emitbin,
@@ -129,7 +128,8 @@ void (*opcode[])(unsigned, void *) = {
[OSWITCH] = emitswitch,
[OSWITCHT] = emitswitcht,
[OPAR] = emitbin,
- [OCALL] = emitbin
+ [OCALL] = emitbin,
+ [OINIT] = emitinit
};
void
@@ -284,6 +284,18 @@ emittype(Type *tp)
}
static void
+emitinit(unsigned op, void *arg)
+{
+ Node *np = arg;
+
+ puts("(");
+ emitexp(OEXPR, np->right);
+ puts(")");
+ np->right = NULL;
+ freetree(np);
+}
+
+static void
emitdcl(unsigned op, void *arg)
{
Symbol *sym = arg;
diff --git a/cc1/decl.c b/cc1/decl.c
@@ -661,6 +661,7 @@ identifier(struct decl *dcl)
flags |= (curctx == GLOBALCTX) ? ISPRIVATE : ISLOCAL;
break;
case TYPEDEF:
+ flags |= ISTYPEDEF;
sym->token = TYPEIDEN;
break;
}
@@ -668,8 +669,6 @@ identifier(struct decl *dcl)
}
/* 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 @@ decl(void)
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);
diff --git a/cc1/expr.c b/cc1/expr.c
@@ -980,24 +980,46 @@ condexpr(void)
/* 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('}');
- return;
- }
- np = expr();
- if ((sym->flags & ISLOCAL) == 0) {
- emit(OEXPR, assignop(OINIT, varnode(sym), np));
+ initlist();
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);
+ }
}