scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit b86fdca96b49c9000d32995a427f2ac8fad4ef6a
parent 73e8f02ee56e42272698ef92ec8b593cec130843
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 24 Jul 2015 17:27:23 +0200

Merge branch 'master' of ssh://suckless.org/gitrepos/scc

Conflicts:
	cc1/cc1.h

Diffstat:
cc1/cc1.h | 3+++
cc1/code.c | 44++++++++++++++++++++++++++++++++++++++++++--
cc1/decl.c | 11+++++------
cc1/expr.c | 39++++++++++++++++++++++++++++++++-------
cc1/stmt.c | 7++-----
5 files changed, 84 insertions(+), 20 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -327,10 +327,13 @@ extern Node *constnode(Symbol *sym); extern Node *sizeofnode(Type *tp); extern void freetree(Node *np); extern Node *simplify(unsigned char, Type *tp, Node *lp, Node *rp); +extern Node *usimplify(unsigned char op, Type *tp, Node *np); #define BTYPE(np) ((np)->type->op) /* expr.c */ extern Node *expr(void), *negate(Node *np), *constexpr(void); +extern Node *convert(Node *np, Type *tp1, char iscast); +extern Node *iszero(Node *np), *eval(Node *np), *iconstexpr(void); /* cpp.c */ extern void icpp(void); diff --git a/cc1/code.c b/cc1/code.c @@ -463,8 +463,6 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp) case OOR: FOLDINT(sym, ls, rs, ||); break; - default: - abort(); } break; case FLOAT: @@ -481,3 +479,45 @@ division_by_0: no_simplify: return node(op, tp, lp, rp); } + +#define UFOLDINT(sym, ls, op) (((sym)->type->sign) ? \ + ((sym)->u.i = (op (ls)->u.i)) : \ + ((sym)->u.u = (op (ls)->u.u))) + +Node * +usimplify(unsigned char op, Type *tp, Node *np) +{ + Symbol *sym, *ns; + + if (!np->constant) + goto no_simplify; + ns = np->sym; + + switch (tp->op) { + case INT: + switch (op) { + case ONEG: + sym = newsym(NS_IDEN); + sym->type = tp; + UFOLDINT(sym, ns, -); + break; + case OCPL: + sym = newsym(NS_IDEN); + sym->type = tp; + UFOLDINT(sym, ns, ~); + break; + default: + goto no_simplify; + } + break; + case FLOAT: + /* TODO: implement floats */ + default: + goto no_simplify; + } + + return constnode(sym); + +no_simplify: + return node(op, tp, np, NULL); +} diff --git a/cc1/decl.c b/cc1/decl.c @@ -39,17 +39,16 @@ queue(struct dcldata *dp, unsigned op, short nelem, void *data) static struct dcldata * arydcl(struct dcldata *dp) { - Node *np; + Node *np = NULL; TINT n; expect('['); - np = (yytoken != ']') ? constexpr() : NULL; + if (yytoken != ']') { + if ((np = iconstexpr()) == NULL) + error("invalid storage size"); + } expect(']'); - /* - * TODO: check that the type of the constant expression - * is the correct, that in this case should be int - */ n = (np == NULL) ? 0 : np->sym->u.i; freetree(np); diff --git a/cc1/expr.c b/cc1/expr.c @@ -88,7 +88,7 @@ numericaluop(char op, Node *np) case FLOAT: if (op == OADD) return np; - return node(op, np->type, np, NULL); + return usimplify(op, np->type, np); default: error("unary operator requires integer operand"); } @@ -100,7 +100,7 @@ integeruop(char op, Node *np) np = eval(np); if (BTYPE(np) != INT) error("unary operator requires integer operand"); - return node(op, np->type, np, NULL); + return usimplify(op, np->type, np); } static Node * @@ -123,13 +123,18 @@ convert(Node *np, Type *tp, char iscast) if (eqtype(np->type, tp)) return np; switch (BTYPE(np)) { - case ENUM: case INT: case FLOAT: + case ENUM: + case INT: + case FLOAT: switch (tp->op) { case PTR: if (!iscast || BTYPE(np) == FLOAT) return NULL; /* PASSTHROUGH */ - case INT: case FLOAT: case ENUM: case VOID: + case INT: + case FLOAT: + case ENUM: + case VOID: break; default: return NULL; @@ -137,7 +142,9 @@ convert(Node *np, Type *tp, char iscast) break; case PTR: switch (tp->op) { - case ENUM: case INT: case VOID: /* TODO: allow p = 0 */ + case ENUM: /* TODO: allow p = 0 */ + case INT: + case VOID: if (!iscast) return NULL;; break; @@ -851,12 +858,30 @@ constexpr(void) Node *np; np = ternary(); - if (!np->constant) - error("constant expression required"); + if (!np->constant) { + freetree(np); + return NULL; + } return np; } Node * +iconstexpr(void) +{ + Node *np; + + if ((np = constexpr()) == NULL) + return NULL; + + if (np->type->op != INT) { + freetree(np); + return NULL; + } + + return convert(np, inttype, 0); +} + +Node * expr(void) { Node *lp, *rp; diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -9,8 +9,6 @@ Symbol *curfun; -extern Node *convert(Node *np, Type *tp1, char iscast); -extern Node *iszero(Node *np), *eval(Node *np); static void stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch); static void @@ -251,9 +249,8 @@ Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) expect(CASE); if (!lswitch) error("case label not within a switch statement"); - np = expr(); - if ((np = convert(np, inttype, 0)) == NULL) - error("incorrect type in case statement"); + if ((np = iconstexpr()) == NULL) + error("case label does not reduce to an integer constant"); expect(':'); pcase = xmalloc(sizeof(*pcase)); pcase->expr = np;