shithub: scc

Download patch

ref: dac8c31a33977081e510992580a5e47c2d3ffe84
parent: 034a823e68386a5e18bac3d796658fbf87f7654f
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sun Jul 26 15:54:41 EDT 2015

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().

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -335,6 +335,7 @@
 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);
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -391,6 +391,9 @@
 	((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 @@
 
 	/* 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 @@
 		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 @@
 		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;
@@ -486,6 +499,24 @@
 			if (rs->u.f == 0.0)
 				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;
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -303,10 +303,10 @@
 	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 @@
 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 @@
 Node *
 iszero(Node *np)
 {
-	if (isnodecmp(np))
+	if (isnodecmp(np->op))
 		return np;
 	return compare(ONE, np, constnode(zero));
 }