scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 4f8980c62a63c938a957a469bae8fa9ed88e399f
parent ff4af4d2c1a4fcf5e3e13ed4c03578b4495b993f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 10 Aug 2016 15:04:46 +0200

[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.

Diffstat:
Mcc1/cc1.h | 1+
Mcc1/code.c | 4+++-
Mcc1/expr.c | 65+++++++++++++++++++++++++++++++++++++++--------------------------
Mcc1/fold.c | 6++++--
Mcc2/cc2.h | 3++-
Mcc2/parser.c | 3++-
6 files changed, 51 insertions(+), 31 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -200,6 +200,7 @@ enum op { OBAND, OBXOR, OBOR, + OSNEG, ONEG, OCPL, OAND, diff --git a/cc1/code.c b/cc1/code.c @@ -50,7 +50,8 @@ char *optxt[] = { [OA_XOR] = ":^", [OA_OR] = ":|", [OADDR] = "'", - [ONEG] = "_", + [OSNEG] = "_", + [ONEG] = "n", [OCPL] = "~", [OAND] = "a", [OOR] = "o", @@ -104,6 +105,7 @@ void (*opcode[])(unsigned, void *) = { [OA_XOR] = emitbin, [OA_OR] = emitbin, [OADDR] = emitbin, + [OSNEG] = emitbin, [ONEG] = emitbin, [OCPL] = emitbin, [OAND] = emitbin, diff --git a/cc1/expr.c b/cc1/expr.c @@ -37,22 +37,6 @@ cmpnode(Node *np, TUINT val) 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 @@ numericaluop(char op, Node *np) 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 @@ int 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 @@ negop(int op) 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 @@ exp2cond(Node *np, char neg) { 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 @@ unary(int needdecay) 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; diff --git a/cc1/fold.c b/cc1/fold.c @@ -188,7 +188,8 @@ foldint(int op, Symbol *res, TINT l, TINT r) 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 @@ folduint(int op, Symbol *res, TUINT l, TUINT r) 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; diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -81,7 +81,7 @@ enum op { OBXOR = '^', OCPL = '~', OASSIG = ':', - ONEG = '_', + OSNEG = '_', OCALL = 'c', OPAR = 'p', OFIELD = '.', @@ -91,6 +91,7 @@ enum op { OADDR = '\'', OAND = 'a', OOR = 'o', + ONEG = 'n', OPTR = '@', OCAST = 'g', OINC = 'i', diff --git a/cc2/parser.c b/cc2/parser.c @@ -92,11 +92,12 @@ static struct decoc { ['\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},