commit 02fb869bc63d7b49765e993ba2c8115e0bc54251
parent 10fc3c6fb48ebc45f6322d86d6692e7d568545a1
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 15 Apr 2014 17:00:20 +0200
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.
Diffstat:
M | cc.h | | | 18 | +++++++++++------- |
M | expr.c | | | 35 | +++++++++++++++-------------------- |
2 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/cc.h b/cc.h
@@ -216,16 +216,19 @@ typedef struct node {
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 @@ extern Node
#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
diff --git a/expr.c b/expr.c
@@ -224,22 +224,21 @@ incompatibles:
}
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 @@ error:
}
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 @@ unary(void)
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 @@ assign(void)
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 @@ assign(void)
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: