scc

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

commit 04eaf8bf9813e47819a823534b8b53e481088f77
parent 585dc6d025dabe3e95271084e27e6c833c8c3dbf
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 22 Jul 2015 14:30:27 +0200

Simplify multiplicative expressions

Diffstat:
Mcc1/code.c | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mcc1/expr.c | 1+
2 files changed, 99 insertions(+), 17 deletions(-)

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/expr.c b/cc1/expr.c @@ -667,6 +667,7 @@ mul(void) } next(); np = (*fun)(op, np, cast()); + np = simplify(np); } }