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:
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));
}