commit 1814a219b69466faf91e429a2fa30671d4e9a26b
parent 8a12777187779837b55e84a8cae473f2b41527cd
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Wed, 22 Jul 2015 18:15:30 +0200
Merge branch 'master' of ssh://suckless.org/gitrepos/scc
Diffstat:
7 files changed, 155 insertions(+), 41 deletions(-)
diff --git a/cc1/TODO b/cc1/TODO
@@ -2,7 +2,6 @@
* Verify correctness in initializators
* emit initializators
* emit structures definition
-* Assign const expression value to enum members
* Define array types based in the value of constant expressions
* Rewrite decl.c and use only one decl function with a function pointer
parameter
@@ -13,7 +12,6 @@
* Rewrite error recovery code, and ensure correct state after recovery
* Allow comparisions between pointers and 0
* Implement function calls
-* Implement enum type in eqtype()
* Parse correctly all integer and float constants
* Add C99 features (almost all the new features of C99 are missed)
* Add correct emit for any kind of constant
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -130,7 +130,8 @@ enum {
ISFIELD = 32,
ISPARAM = 64,
ISEXTERN = 128,
- ISUSED = 256
+ ISUSED = 256,
+ ISCONSTANT = 512
};
diff --git a/cc1/code.c b/cc1/code.c
@@ -124,15 +124,20 @@ void (*opcode[])(unsigned, void *) = {
[OSWITCH] = emitswitch
};
-static Node *simple_sub(Node *), *simple_add(Node *);
+static Node *simple_add(Type *, Node *, Node *),
+ *simple_sub(Type *, Node *, Node *),
+ *simple_mul(Type *, Node *, Node *),
+ *simple_div(Type *, Node *, Node *),
+ *simple_mod(Type *, Node *, Node *);
-static Node *(*opsimp[])(Node *) = {
+static Node *(*opsimp[])(Type *, Node *, Node *) = {
[OADD] = simple_add,
- [OSUB] = simple_sub
-
+ [OSUB] = simple_sub,
+ [OMUL] = simple_mul,
+ [ODIV] = simple_div,
+ [OMOD] = simple_mod
};
-
void
freetree(Node *np)
{
@@ -388,10 +393,83 @@ sizeofnode(Type *tp)
}
static Node *
-simple_add(Node *np)
+simple_mod(Type *tp, Node *lp, Node *rp)
+{
+ Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+ switch (tp->op) {
+ case INT:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
+ if (tp->sign) {
+ if (rs->u.i == 0)
+ goto division_by_0;
+ sym->u.i = ls->u.i % rs->u.i;
+ } else {
+ if (rs->u.u == 0)
+ goto division_by_0;
+ sym->u.u = ls->u.u % rs->u.u;
+ }
+ return constnode(sym);
+ default:
+ return NULL;
+ }
+
+division_by_0:
+ warn("division by 0");
+ return NULL;
+}
+
+static Node *
+simple_div(Type *tp, Node *lp, Node *rp)
+{
+ Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+ switch (tp->op) {
+ case INT:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
+ if (tp->sign) {
+ if (rs->u.i == 0)
+ goto division_by_0;
+ sym->u.i = ls->u.i / rs->u.i;
+ } else {
+ if (rs->u.u == 0)
+ goto division_by_0;
+ sym->u.u = ls->u.u / rs->u.u;
+ }
+ return constnode(sym);
+ default:
+ return NULL;
+ }
+
+division_by_0:
+ warn("division by 0");
+ return NULL;
+}
+
+static Node *
+simple_mul(Type *tp, Node *lp, Node *rp)
+{
+ Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+ switch (tp->op) {
+ case INT:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
+ if (tp->sign)
+ sym->u.i = ls->u.i * rs->u.i;
+ else
+ sym->u.u = ls->u.u * rs->u.u;
+ return constnode(sym);
+ default:
+ return NULL;
+ }
+}
+
+static Node *
+simple_add(Type *tp, Node *lp, Node *rp)
{
- Node *lp = np->left, *rp = np->right;
- Type *tp = np->type;
Symbol *sym, *ls = lp->sym, *rs = rp->sym;
switch (tp->op) {
@@ -402,18 +480,15 @@ simple_add(Node *np)
sym->u.i = ls->u.i + rs->u.i;
else
sym->u.u = ls->u.u + rs->u.u;
- freetree(np);
return constnode(sym);
default:
- return np;
+ return NULL;
}
}
static Node *
-simple_sub(Node *np)
+simple_sub(Type *tp, Node *lp, Node *rp)
{
- Node *lp = np->left, *rp = np->right;
- Type *tp = np->type;
Symbol *sym, *ls = lp->sym, *rs = rp->sym;
switch (tp->op) {
@@ -424,17 +499,23 @@ simple_sub(Node *np)
sym->u.i = ls->u.i - rs->u.i;
else
sym->u.u = ls->u.u - rs->u.u;
- freetree(np);
return constnode(sym);
default:
- return np;
+ return NULL;
}
}
Node *
simplify(Node *np)
{
- if (!np->left->constant || !np->right->constant)
+ Node *new, *lp = np->left, *rp = np->right;
+
+ if (!lp->constant || !rp->constant)
return np;
- return (*opsimp[np->op])(np);
+ new = (*opsimp[np->op])(np->type, lp, rp);
+ if (new) {
+ freetree(np);
+ np = new;
+ }
+ return np;
}
diff --git a/cc1/decl.c b/cc1/decl.c
@@ -51,6 +51,7 @@ arydcl(struct dcldata *dp)
* is the correct, that in this case should be int
*/
n = (np == NULL) ? 0 : np->sym->u.i;
+ freetree(np);
return queue(dp, ARY, n, NULL);
}
@@ -215,11 +216,13 @@ specifier(unsigned *sclass)
switch (yylval.token) {
case ENUM:
dcl = enumdcl;
- p = &type; break;
+ p = &type;
+ break;
case STRUCT:
case UNION:
dcl = structdcl;
- p = &type; break;
+ p = &type;
+ break;
case VOID:
case BOOL:
case CHAR:
@@ -230,7 +233,8 @@ specifier(unsigned *sclass)
break;
case SIGNED:
case UNSIGNED:
- p = &sign; break;
+ p = &sign;
+ break;
case LONG:
if (size == LONG) {
size = LLONG;
@@ -251,6 +255,7 @@ specifier(unsigned *sclass)
if (size || sign)
goto invalid_type;
tp = (*dcl)();
+ goto return_type;
} else {
next();
}
@@ -290,7 +295,7 @@ static Symbol *
newtag(void)
{
Symbol *sym;
- unsigned tag = yylval.token;
+ int op, tag = yylval.token;
static unsigned ns = NS_STRUCTS;
setnamespace(NS_TAG);
@@ -299,6 +304,7 @@ newtag(void)
case IDEN:
case TYPEIDEN:
sym = yylval.sym;
+ install(NS_TAG);
next();
break;
default:
@@ -313,8 +319,8 @@ newtag(void)
}
sym->flags |= ISDEFINED;
- if (sym->type->op != tag)
- error("'%s' defined as wrong kind of tag", yytext);
+ if ((op = sym->type->op) != tag && op != INT)
+ error("'%s' defined as wrong kind of tag", sym->name);
return sym;
}
@@ -385,28 +391,36 @@ static Type *
enumdcl(void)
{
Type *tp;
- Symbol *sym;
- int val = 0;
+ Symbol *sym, *tagsym;
+ int val;
- tp = newtag()->type;
+ tagsym = newtag();
+ tp = tagsym->type;
- if (yytoken == ';')
+ if (!accept('{'))
return tp;
-
- expect('{');
if (tp->defined)
- error("redefinition of enumeration '%s'", yytext);
+ error("redefinition of enumeration '%s'", tagsym->name);
tp->defined = 1;
- while (yytoken != '}') {
+ for (val = 0; yytoken != ')'; ++val) {
if (yytoken != IDEN)
unexpected();
if ((sym = install(NS_IDEN)) == NULL)
error("'%s' redeclared as different kind of symbol", yytext);
next();
+ sym->flags |= ISCONSTANT;
sym->type = inttype;
- if (accept('='))
- constexpr();
- sym->u.i = val++;
+ if (accept('=')) {
+ Node *np = constexpr();
+ /*
+ * TODO: check that the type of the constant
+ * expression is the correct, that in this
+ * case should be int
+ */
+ val = np->sym->u.i;
+ freetree(np);
+ }
+ sym->u.i = val;
if (!accept(','))
break;
}
diff --git a/cc1/expr.c b/cc1/expr.c
@@ -667,6 +667,7 @@ mul(void)
}
next();
np = (*fun)(op, np, cast());
+ np = simplify(np);
}
}
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -231,6 +231,7 @@ convert:
tp = ctype(INT, sign, size);
sym = newsym(NS_IDEN);
sym->type = tp;
+ sym->flags |= ISCONSTANT;
v = strtol(s, NULL, base);
if (tp == inttype)
sym->u.i = v;
@@ -358,6 +359,7 @@ repeat:
yylen = bp - yytext + 1;
yylval.sym = newsym(NS_IDEN);
+ yylval.sym->flags |= ISCONSTANT;
yylval.sym->u.s = xstrdup(yytext+1);
yylval.sym->type = mktype(chartype, ARY, yylen - 2, NULL);
*bp++ = '"';
@@ -387,6 +389,8 @@ iden(void)
*/
sym = nextsym(sym, lex_ns);
}
+ if (sym->flags & ISCONSTANT)
+ return CONSTANT;
if (sym->token != IDEN)
yylval.token = sym->u.token;
return sym->token;
diff --git a/cc1/types.c b/cc1/types.c
@@ -292,10 +292,25 @@ mktype(Type *tp, unsigned op, short nelem, void *data)
type.n.elem = nelem;
type.ns = 0;
- if (op == ARY && nelem == 0 || op == STRUCT || op == UNION)
- type.defined = 0;
- else
+
+ switch (op) {
+ case ARY:
+ if (nelem == 0)
+ goto no_defined;
+ /* PASSTROUGH */
+ case FTN:
+ case PTR:
type.defined = 1;
+ break;
+ case ENUM:
+ type.printed = 1;
+ /* PASSTROUGH */
+ case STRUCT:
+ case UNION:
+ no_defined:
+ type.defined = 0;
+ break;
+ }
t = (op ^ (uintptr_t) tp >> 3) & NR_TYPE_HASH-1;
tbl = &typetab[t];
@@ -336,7 +351,7 @@ eqtype(Type *tp1, Type *tp2)
}
return 1;
case ENUM:
- /* TODO: Check when two enum are the same type */
+ break;
case INT: case FLOAT:
return tp1->letter == tp2->letter;
default: