shithub: scc

Download patch

ref: 6c4bf5ed78393449e623638295c2e8f357e5ba54
parent: 14fcfac5df605f4349cfe6be78ca1cb9c5d6fabe
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Aug 10 11:04:46 EDT 2016

[cc1 cc2] Do not apply DeMorgan to logic operators

Applying the DeMorgan rules is more complex that the code was making,
because it means that we have to negate all the comparision nodes
recursively. The best option is to create a new logic negation node
and do not try to fold anything.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -200,6 +200,7 @@
 	OBAND,
 	OBXOR,
 	OBOR,
+	OSNEG,
 	ONEG,
 	OCPL,
 	OAND,
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -50,7 +50,8 @@
 	[OA_XOR] = ":^",
 	[OA_OR] = ":|",
 	[OADDR] = "'",
-	[ONEG] = "_",
+	[OSNEG] = "_",
+	[ONEG] = "n",
 	[OCPL] = "~",
 	[OAND] = "a",
 	[OOR] = "o",
@@ -104,6 +105,7 @@
 	[OA_XOR] = emitbin,
 	[OA_OR] = emitbin,
 	[OADDR] = emitbin,
+	[OSNEG] = emitbin,
 	[ONEG] = emitbin,
 	[OCPL] = emitbin,
 	[OAND] = emitbin,
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -37,22 +37,6 @@
 	return 0;
 }
 
-int
-isnodecmp(int op)
-{
-	switch (op) {
-	case OEQ:
-	case ONE:
-	case OLT:
-	case OGE:
-	case OLE:
-	case OGT:
-		return 1;
-	default:
-		return 0;
-	}
-}
-
 static Node *
 promote(Node *np)
 {
@@ -251,7 +235,7 @@
 	if (!(np->type->prop & TARITH))
 		error("unary operator requires numerical operand");
 	np = promote(np);
-	if (op == ONEG && np->op == ONEG)
+	if (op == OSNEG && np->op == OSNEG)
 		return np->left;
 	if (op == OADD)
 		return np;
@@ -413,8 +397,6 @@
 negop(int op)
 {
 	switch (op) {
-	case OAND: return OOR;
-	case OOR:  return OAND;
 	case OEQ:  return ONE;
 	case ONE:  return OEQ;
 	case OLT:  return OGE;
@@ -429,11 +411,32 @@
 Node *
 negate(Node *np)
 {
-	if (np->op == OSYM) {
+	int op = np->op;
+
+	switch (np->op) {
+	case OSYM:
 		assert(np->flags&NCONST && np->type->prop&TINTEGER);
 		np->sym = (np->sym->u.i) ? zero : one;
-	} else {
-		np->op = negop(np->op);
+		break;
+	case OOR:
+	case OAND:
+		if (np->op == ONEG) {
+			Node *new = np->left;
+			free(np);
+			return new;
+		}
+		np = node(ONEG, inttype, np, NULL);
+		break;
+	case OEQ:
+	case ONE:
+	case OLT:
+	case OGE:
+	case OLE:
+	case OGT:
+		np->op = negop(op);
+		break;
+	default:
+		abort();
 	}
 
 	return np;
@@ -444,11 +447,21 @@
 {
 	if (np->type->prop & TAGGREG) {
 		errorp("used struct/union type value where scalar is required");
-		np = constnode(zero);
+		return constnode(zero);
 	}
-	if (isnodecmp(np->op))
+	switch (np->op) {
+	case OOR:
+	case OAND:
+	case OEQ:
+	case ONE:
+	case OLT:
+	case OGE:
+	case OLE:
+	case OGT:
 		return (neg) ? negate(np) : np;
-	return compare((neg) ?  OEQ : ONE, np, constnode(zero));
+	default:
+		return compare((neg) ?  OEQ : ONE, np, constnode(zero));
+	}
 }
 
 static Node *
@@ -827,7 +840,7 @@
 	switch (yytoken) {
 	case '!': op = 0;     fun = negation;     break;
 	case '+': op = OADD;  fun = numericaluop; break;
-	case '-': op = ONEG;  fun = numericaluop; break;
+	case '-': op = OSNEG; fun = numericaluop; break;
 	case '~': op = OCPL;  fun = integeruop;   break;
 	case '&': op = OADDR; fun = address;      break;
 	case '*': op = OPTR;  fun = content;      break;
--- a/cc1/fold.c
+++ b/cc1/fold.c
@@ -188,7 +188,8 @@
 	case OLE:   i = l <= r; break;
 	case OEQ:   i = l == r; break;
 	case ONE:   i = l != r; break;
-	case ONEG:  i = -l;     break;
+	case ONEG:  i = !l;     break;
+	case OSNEG: i = -l;     break;
 	case OCPL:  i = ~l;     break;
 	default:    return 0;
 	}
@@ -213,7 +214,8 @@
 	case OBAND: u = l & r;  break;
 	case OBXOR: u = l ^ r;  break;
 	case OBOR:  u = l | r;  break;
-	case ONEG:  u = -l;     break;
+	case ONEG:  u = !l;     break;
+	case OSNEG: u = -l;     break;
 	case OCPL:  u = ~l;     break;
 	case OAND:  i = l && r; goto sign;
 	case OOR:   i = l || r; goto sign;
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -81,7 +81,7 @@
 	OBXOR    = '^',
 	OCPL     = '~',
 	OASSIG   = ':',
-	ONEG     = '_',
+	OSNEG    = '_',
 	OCALL    = 'c',
 	OPAR     = 'p',
 	OFIELD   = '.',
@@ -91,6 +91,7 @@
 	OADDR    = '\'',
 	OAND     = 'a',
 	OOR      = 'o',
+	ONEG     = 'n',
 	OPTR     = '@',
 	OCAST    = 'g',
 	OINC     = 'i',
--- a/cc2/parser.c
+++ b/cc2/parser.c
@@ -92,11 +92,12 @@
 	['\t']  = {     stmt,    NULL,                     0},
 
 	['~']   = {     NULL,   unary, .u.op =          OCPL},
-	['_']   = {     NULL,   unary, .u.op =          ONEG},
+	['_']   = {     NULL,   unary, .u.op =         OSNEG},
 	['\'']  = {     NULL,   unary, .u.op =         OADDR},
 	['@']   = {     NULL,   unary, .u.op =          OPTR},
 	['g']   = {     NULL,   unary, .u.op =         OCAST},
 	['p']   = {     NULL,   unary, .u.op =          OPAR},
+	['n']   = {     NULL,   unary, .u.op =          ONEG},
 
 	['a']   = {     NULL,  binary, .u.op =          OAND},
 	['o']   = {     NULL,  binary, .u.op =           OOR},