scc

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

commit dac8c31a33977081e510992580a5e47c2d3ffe84
parent 034a823e68386a5e18bac3d796658fbf87f7654f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 26 Jul 2015 19:54:41 +0200

Fix simplification of comparision nodes

Comparision nodes have integer type, but the operands cn have
a different type, so we cannot take the decision based in the
type parameter of simplify().

Diffstat:
Mcc1/cc1.h | 1+
Mcc1/code.c | 77++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mcc1/expr.c | 10+++++-----
3 files changed, 60 insertions(+), 28 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -335,6 +335,7 @@ extern Node *usimplify(unsigned char op, Type *tp, Node *np); 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); +extern bool isnodecmp(int op); /* cpp.c */ extern void icpp(void); diff --git a/cc1/code.c b/cc1/code.c @@ -391,6 +391,9 @@ sizeofnode(Type *tp) ((sym)->u.i = ((ls)->u.i op (rs)->u.i)) : \ ((sym)->u.u = ((ls)->u.u op (rs)->u.u))) +#define CMPISYM(sym, ls, rs, op) (((sym)->type->sign) ? \ + ((ls)->u.i op (rs)->u.i) : ((ls)->u.u op (rs)->u.u)) + Node * simplify(unsigned char op, Type *tp, Node *lp, Node *rp) { @@ -403,8 +406,22 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp) /* TODO: Add overflow checkings */ + if (isnodecmp(op)) { + /* + * Comparision nodes have integer type + * but the operands can have different + * type. + */ + switch (BTYPE(lp)) { + case INT: goto cmp_integers; + case FLOAT: goto cmp_floats; + default: goto no_simplify; + } + } + switch (tp->op) { case INT: + cmp_integers: switch (op) { case OADD: FOLDINT(&aux, ls, rs, +); @@ -431,29 +448,6 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp) case OSHR: FOLDINT(&aux, ls, rs, >>); break; - /* - * FIXME: comparision nodes are integers - * but it doesn't mean the operands are - * integers too - */ - case OLT: - FOLDINT(&aux, ls, rs, <); - break; - case OGT: - FOLDINT(&aux, ls, rs, >); - break; - case OGE: - FOLDINT(&aux, ls, rs, >=); - break; - case OLE: - FOLDINT(&aux, ls, rs, <=); - break; - case OEQ: - FOLDINT(&aux, ls, rs, ==); - break; - case ONE: - FOLDINT(&aux, ls, rs, !=); - break; case OBAND: FOLDINT(&aux, ls, rs, &); break; @@ -469,9 +463,28 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp) case OOR: FOLDINT(&aux, ls, rs, ||); break; + case OLT: + aux.u.i = CMPISYM(&aux, ls, rs, <); + break; + case OGT: + aux.u.i = CMPISYM(&aux, ls, rs, >); + break; + case OGE: + aux.u.i = CMPISYM(&aux, ls, rs, >=); + break; + case OLE: + aux.u.i = CMPISYM(&aux, ls, rs, <=); + break; + case OEQ: + aux.u.i = CMPISYM(&aux, ls, rs, ==); + break; + case ONE: + aux.u.i = CMPISYM(&aux, ls, rs, !=); + break; } break; case FLOAT: + cmp_floats: switch (op) { case OADD: aux.u.f = ls->u.f + rs->u.f; @@ -487,6 +500,24 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp) goto division_by_0; aux.u.f = ls->u.f / rs->u.f; break; + case OLT: + aux.u.i = ls->u.f < rs->u.f; + break; + case OGT: + aux.u.i = ls->u.f > rs->u.f; + break; + case OGE: + aux.u.i = ls->u.f >= rs->u.f; + break; + case OLE: + aux.u.i = ls->u.f <= rs->u.f; + break; + case OEQ: + aux.u.i = ls->u.f == rs->u.f; + break; + case ONE: + aux.u.i = ls->u.f != rs->u.f; + break; } break; default: diff --git a/cc1/expr.c b/cc1/expr.c @@ -303,10 +303,10 @@ negate(Node *np) return np; } -static bool -isnodecmp(Node *np) +bool +isnodecmp(int op) { - switch (np->op) { + switch (op) { case OEQ: case ONE: case OLT: @@ -322,7 +322,7 @@ isnodecmp(Node *np) static Node * exp2cond(Node *np, char neg) { - if (isnodecmp(np)) + if (isnodecmp(np->op)) return (neg) ? negate(np) : np; return compare(ONE ^ neg, np, constnode(zero)); } @@ -374,7 +374,7 @@ array(Node *lp, Node *rp) Node * iszero(Node *np) { - if (isnodecmp(np)) + if (isnodecmp(np->op)) return np; return compare(ONE, np, constnode(zero)); }