scc

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

commit ef05ad6ff2560acd1364b1d90cf52ec95603bc9e
parent 9e40c0c4f8f15b13a2a39bab393f5a921ec83275
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 15 Apr 2014 11:18:54 +0200

Add logical negation

Logical negation are transformed into ternary operators.

Diffstat:
Mcc.h | 2+-
Mexpr.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mlex.c | 1-
Mmain.c | 4+++-
4 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/cc.h b/cc.h @@ -225,7 +225,7 @@ enum { 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, + ONEG, OCPL, OEXC }; extern void diff --git a/expr.c b/expr.c @@ -5,8 +5,22 @@ #define SWAP(x1, x2, t) (t = x1, x1 = x2, x2 = t) +static Symbol *zero, *one; + Node *expr(void); +void +init_expr(void) +{ + static Symbol zdummy, odummy; + + zdummy.type = odummy.type = inttype; + zdummy.u.i = 0; + odummy.u.i = 1; + zero = &zdummy; + one = &odummy; +} + static Node * promote(Node *np) { @@ -243,6 +257,20 @@ error: } static Node * +eval(Node *np, char neg) +{ + Node *ifyes, *ifno, *cmp; + char op; + + ifyes = node(emitconst, inttype, SYM(one), 0); + ifno = node(emitconst, inttype, SYM(zero), 0); + cmp = node(emitconst, inttype, SYM(zero), 0); + op = (neg) ? OEQ : ONE; + + return ternarycode(compare(op, np, cmp), ifyes, ifno); +} + +static Node * incdec(Node *np, char op) { Type *tp; @@ -365,11 +393,11 @@ unary(void) case INC: case DEC: op = (yytoken == INC) ? OINC : ODEC; next(); - return incdec(unary(), op); - /* TODO: case '!': */ + return incdec(unary(), op); /* TODO: unary or cast? */ + case '!': op = OEXC; break; /* TODO: case '&': */ /* TODO: case '*': */ - case '+': op = 0; break; + case '+': op = OADD; break; case '~': op = OCPL; break; case '-': op = ONEG; break; default: return postfix(); @@ -380,21 +408,32 @@ unary(void) t = BTYPE(np->type); switch (op) { - case OCPL: + case OEXC: + switch (t) { + case FTN: case ARY: + np = addr2ptr(np); + case INT: case FLOAT: case PTR: + np = eval(np, 1); + break; + default: + goto bad_operand; + } + break; + case OCPL: case OADD: if (t != INT) - goto bad_complement; + goto bad_operand; + if (op == OADD) + break; case ONEG: if (!isarith(t)) - goto bad_arithm; + goto bad_operand; np = unarycode(op, np->type, np); - case 0: - return np; } -bad_complement: - error("bad operand in bit-complement"); -bad_arithm: - error("bad arithmetic operand in unary expression"); + return np; + +bad_operand: + error("bad operand in unary expression"); } static Node * diff --git a/lex.c b/lex.c @@ -28,7 +28,6 @@ integer(char *s, char base) static char ch; /* TODO: implement again */ - type: switch (ch = toupper(getc(yyin))) { case 'L': diff --git a/main.c b/main.c @@ -4,7 +4,8 @@ #include "cc.h" -extern void extdecl(void), init_keywords(void), open_file(const char *file); +extern void extdecl(void), init_keywords(void), + open_file(const char *file), init_expr(void); struct user_opt options; @@ -12,6 +13,7 @@ int main(int argc, char *argv[]) { init_keywords(); + init_expr(); open_file(NULL); for (next(); yytoken != EOFTOK; extdecl()); /* nothing */;