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);
+ }
}
--
⑨