scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

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:
cc.h | 18+++++++++++-------
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: