scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

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:
Mcc1/TODO | 2--
Mcc1/cc1.h | 3++-
Mcc1/code.c | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mcc1/decl.c | 48+++++++++++++++++++++++++++++++-----------------
Mcc1/expr.c | 1+
Mcc1/lex.c | 4++++
Mcc1/types.c | 23+++++++++++++++++++----
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: