scc

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

commit 022b66c883b41558202c1e602ee98c44e8c6a146
parent f9b9be337e76a5a4c16d48639e4a3379d9fdd639
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 23 Jul 2015 10:37:25 +0200

Simplify simplify()

Using overloading in symplify() will generate a lot of
functions very similars, so it is better to use a generic
approach with a big switch.

Diffstat:
Mcc1/code.c | 153+++++++++++++++++++------------------------------------------------------------
1 file changed, 37 insertions(+), 116 deletions(-)

diff --git a/cc1/code.c b/cc1/code.c @@ -130,14 +130,6 @@ static Node *simple_add(Type *, Node *, Node *), *simple_div(Type *, Node *, Node *), *simple_mod(Type *, Node *, Node *); -static Node *(*opsimp[])(Type *, Node *, Node *) = { - [OADD] = simple_add, - [OSUB] = simple_sub, - [OMUL] = simple_mul, - [ODIV] = simple_div, - [OMOD] = simple_mod -}; - void freetree(Node *np) { @@ -392,130 +384,59 @@ sizeofnode(Type *tp) return constnode(sym); } -static Node * -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; - } +#define SYMICMP(sym, val) (((sym)->type->sign) ? \ + (sym)->u.i == (val) : (sym)->u.u == (val)) -division_by_0: - warn("division by 0"); - return NULL; -} +#define FOLDINT(sym, ls, rs, op) (((sym)->type->sign) ? \ + ((sym)->u.i = ((ls)->u.i op (rs)->u.i)) : \ + ((sym)->u.u = ((ls)->u.u op (rs)->u.u))) -static Node * -simple_div(Type *tp, Node *lp, Node *rp) +Node * +simplify(Node *np) { + Node *lp = np->left, *rp = np->right; Symbol *sym, *ls = lp->sym, *rs = rp->sym; + Type *tp = np->type; + + if (!lp->constant || !rp->constant) + return np; switch (tp->op) { case INT: sym = newsym(NS_IDEN); sym->type = tp; - if (tp->sign) { - if (rs->u.i == 0) + switch (np->op) { + case OADD: + FOLDINT(sym, ls, rs, +); + break; + case OSUB: + FOLDINT(sym, ls, rs, -); + break; + case OMUL: + FOLDINT(sym, ls, rs, *); + break; + case ODIV: + if (SYMICMP(sym, 0)) goto division_by_0; - sym->u.i = ls->u.i / rs->u.i; - } else { - if (rs->u.u == 0) + FOLDINT(sym, ls, rs, /); + break; + case OMOD: + if (SYMICMP(sym, 0)) goto division_by_0; - sym->u.u = ls->u.u / rs->u.u; + FOLDINT(sym, ls, rs, %); + break; + default: + abort(); } - return constnode(sym); + break; default: - return NULL; + return np; } + freetree(np); + return constnode(sym); + 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) -{ - 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_sub(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; - } -} - -Node * -simplify(Node *np) -{ - Node *new, *lp = np->left, *rp = np->right; - - if (!lp->constant || !rp->constant) - return np; - new = (*opsimp[np->op])(np->type, lp, rp); - if (new) { - freetree(np); - np = new; - } return np; }