shithub: scc

Download patch

ref: 02fb869bc63d7b49765e993ba2c8115e0bc54251
parent: 10fc3c6fb48ebc45f6322d86d6692e7d568545a1
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Apr 15 13:00:20 EDT 2014

Evaluate logical and relational operators before assigning

These operators generate 0 or 1, if the value if equal or different
to 0, so in some place this transformation must be done.

--- a/cc.h
+++ b/cc.h
@@ -216,16 +216,19 @@
 	struct node *childs[];
 } Node;
 
-typedef void (*Inst)(Node *);
+typedef void (*Inst)(Node *); /* TODO: remove this typedef */
 
 enum {
-	OCAST, OPTR, OADD, OARY, OSIZE, OMUL, OSUB,
-	OINC, ODEC, OPINC, OPDEC, ODIV, OMOD, OSHL,
-	OSHR, OLT, OGT, OGE, OLE, OEQ, ONE, OBAND,
-	OBXOR, OBOR, OASSIGN, OA_MUL, OA_DIV,
+	OCAST = 1, OPTR, OADD, OARY, OSIZE, OMUL, OSUB,
+	OINC, ODEC, OPINC, OPDEC, ODIV, OMOD, OSHL, OSHR,
+	OBAND, OBXOR, OBOR, OASSIGN, OA_MUL, OA_DIV,
 	OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR,
-	OA_AND, OA_XOR, OA_OR, OADDR, OAND, OOR,
-	ONEG, OCPL, OEXC
+	OA_AND, OA_XOR, OA_OR, OADDR,ONEG, OCPL, OEXC,
+	/*
+	  * Complementary relational operators only differ in less
+	 * significant bit
+	 */
+	OEQ = 0x40, ONE, OLT, OGE, OLE, OGT, OAND, OOR
 };
 
 extern void
@@ -246,5 +249,6 @@
 #define TYP(s) ((union unode) {.type = s})
 #define ISNODESYM(n) ((n)->code == emitsym)
 #define ISNODEBIN(n) ((n)->code == emitbin)
+#define ISNODELOG(n) (ISNODEBIN(n) && (n)->u.op & 0x40)
 
 #endif
--- a/expr.c
+++ b/expr.c
@@ -224,22 +224,21 @@
 }
 
 static Node *
-exp2cond(Node *np)
+exp2cond(Node *np, char neg)
 {
-	if (ISNODEBIN(np)) {
-		switch (np->u.op) {
-		case OLT: case OGT: case OGE: case OLE: case OEQ: case ONE:
+	if (ISNODELOG(np)) {
+			np->u.op ^= neg;
 			return np;
-		}
 	}
-	return compare(ONE, np, constcode(zero));
+
+	return compare(ONE ^ neg, np, constcode(zero));
 }
 
 static Node *
 logic(char op, Node *np1, Node *np2)
 {
-	np1 = exp2cond(np1);
-	np2 = exp2cond(np2);
+	np1 = exp2cond(np1, 0);
+	np2 = exp2cond(np2, 0);
 	return bincode(op, inttype, np1, np2);
 }
 
@@ -271,17 +270,14 @@
 }
 
 static Node *
-eval(Node *np, char neg)
+eval(Node *np)
 {
-	Node *ifyes, *ifno, *cmp;
-	char op;
+	Node *ifyes, *ifno;
 
-	ifyes = constcode(one);
-	ifno = constcode(zero);
-	cmp = constcode(zero);
-	op = (neg) ?  OEQ : ONE;
+	if (!ISNODELOG(np))
+		return np;
 
-	return ternarycode(compare(op, np, cmp), ifyes, ifno);
+	return ternarycode(np, constcode(one), constcode(zero));
 }
 
 static Node *
@@ -434,7 +430,7 @@
 			case FTN: case ARY:
 				np = addr2ptr(np);
 			case INT: case FLOAT: case PTR:
-				return eval(np, 1);
+				return exp2cond(np, 1);
 				break;
 			default:
 				goto bad_operand;
@@ -681,7 +677,7 @@
 		case AND_EQ: op = OA_AND;  break;
 		case XOR_EQ: op = OA_XOR;  break;
 		case OR_EQ:  op = OA_OR;   break;
-		default:  goto return_np;
+		default: return np1;
 		}
 		next();
 		np2 = assign();
@@ -689,12 +685,11 @@
 			goto nolvalue;
 		if (isconst(np1->type->op))
 			goto const_mod;
-		/* TODO: if it necessary a 0 comparision? */
+		np2 = eval(np2);
 		if ((np2 = convert(np2, np1->type)) == NULL)
 			goto incompatibles;
 		np1 = bincode(op, np1->type, np1, np2);
 	}
-return_np:
 	return np1;
 
 const_mod: