scc

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

commit 138e890629e9b4059e62fd6111be6ec01afb97ec
parent 12556580f6096789284e4012602c094fef87795e
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 27 Aug 2015 17:24:14 +0200

Move fold stuff to an own file

This is going to be large, so it is better move it away
from expr.c, because it is increasing the size of it too much.

Diffstat:
cc1/Makefile | 2+-
cc1/cc1.h | 6++++++
cc1/expr.c | 332+------------------------------------------------------------------------------
cc1/fold.c | 333+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 344 insertions(+), 329 deletions(-)

diff --git a/cc1/Makefile b/cc1/Makefile @@ -1,7 +1,7 @@ include ../config.mk OBJS = types.o decl.o lex.o error.o symbol.o main.o expr.o \ - code.o stmt.o cpp.o + code.o stmt.o cpp.o fold.o all: cc1 diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -347,11 +347,17 @@ extern Node *sizeofnode(Type *tp); extern void freetree(Node *np); #define BTYPE(np) ((np)->type->op) +/* fold.c */ +extern Node *simplify(unsigned char op, Type *tp, Node *lp, Node *rp); +extern Node *usimplify(unsigned char op, Type *tp, Node *np); +extern Node *constconv(Node *np, Type *newtp); + /* expr.c */ extern Node *expr(void), *negate(Node *np), *constexpr(void); extern Node *convert(Node *np, Type *tp1, char iscast); extern Node *eval(Node *np), *iconstexpr(void), *condition(void); extern Node *exp2cond(Node *np, char neg); +extern bool isnodecmp(int op); /* cpp.c */ extern void icpp(void); diff --git a/cc1/expr.c b/cc1/expr.c @@ -8,9 +8,12 @@ #include "cc1.h" +#define SYMICMP(sym, val) (((sym)->type->sign) ? \ + (sym)->u.i == (val) : (sym)->u.u == (val)) + Node *expr(void); -static bool +bool isnodecmp(int op) { switch (op) { @@ -26,285 +29,6 @@ isnodecmp(int op) } } -#define SYMICMP(sym, val) (((sym)->type->sign) ? \ - (sym)->u.i == (val) : (sym)->u.u == (val)) - -#define FOLDINT(sym, ls, rs, op) (((sym)->type->sign) ? \ - ((sym)->u.i = ((ls)->u.i op (rs)->u.i)) : \ - ((sym)->u.u = ((ls)->u.u op (rs)->u.u))) - -#define CMPISYM(sym, ls, rs, op) (((sym)->type->sign) ? \ - ((ls)->u.i op (rs)->u.i) : ((ls)->u.u op (rs)->u.u)) - -static Node * -simplify(unsigned char op, Type *tp, Node *lp, Node *rp) -{ - Symbol *sym, *ls, *rs, aux; - int iszero, isone, noconst = 0; - - if (!lp->constant && !rp->constant) - goto no_simplify; - if (!rp->constant) { - Node *np; - np = lp; - lp = rp; - rp = np; - } - if (!lp->constant) - noconst = 1; - - ls = lp->sym, rs = rp->sym; - aux.type = tp; - - /* TODO: Add overflow checkings */ - - if (isnodecmp(op)) { - /* - * Comparision nodes have integer type - * but the operands can have different - * type. - */ - switch (BTYPE(lp)) { - case INT: goto cmp_integers; - case FLOAT: goto cmp_floats; - default: goto no_simplify; - } - } - - switch (tp->op) { - case PTR: - case INT: - cmp_integers: - iszero = SYMICMP(rs, 0); - isone = SYMICMP(rs, 1); - switch (op) { - case OADD: - if (iszero) - return lp; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, +); - break; - case OSUB: - if (iszero) - return lp; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, -); - break; - case OMUL: - if (isone) - return lp; - if (iszero) - return constnode(zero); - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, *); - break; - case ODIV: - if (isone) - return lp; - if (iszero) - goto division_by_0; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, /); - break; - case OMOD: - if (iszero) - goto division_by_0; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, %); - break; - case OSHL: - if (iszero) - return lp; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, <<); - break; - case OSHR: - if (iszero) - return lp; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, >>); - break; - case OBAND: - if (SYMICMP(rs, ~0)) - return lp; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, &); - break; - case OBXOR: - if (iszero) - return lp; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, ^); - break; - case OBOR: - if (iszero) - return lp; - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, |); - break; - case OAND: - if (!iszero) - return lp; - /* TODO: What happens with something like f(0) && 0? */ - if (noconst) - goto no_simplify; - FOLDINT(&aux, ls, rs, &&); - break; - case OOR: - if (iszero) - return lp; - if (noconst) - goto no_simplify; - /* TODO: What happens with something like f(0) || 1? */ - FOLDINT(&aux, ls, rs, ||); - break; - case OLT: - /* TODO: what happens with signess? */ - if (noconst) - goto no_simplify; - aux.u.i = CMPISYM(&aux, ls, rs, <); - break; - case OGT: - /* TODO: what happens with signess? */ - if (noconst) - goto no_simplify; - aux.u.i = CMPISYM(&aux, ls, rs, >); - break; - case OGE: - /* TODO: what happens with signess? */ - if (noconst) - goto no_simplify; - aux.u.i = CMPISYM(&aux, ls, rs, >=); - break; - case OLE: - /* TODO: what happens with signess? */ - if (noconst) - goto no_simplify; - aux.u.i = CMPISYM(&aux, ls, rs, <=); - break; - case OEQ: - /* TODO: what happens with signess? */ - if (noconst) - goto no_simplify; - aux.u.i = CMPISYM(&aux, ls, rs, ==); - break; - case ONE: - /* TODO: what happens with signess? */ - if (noconst) - goto no_simplify; - aux.u.i = CMPISYM(&aux, ls, rs, !=); - break; - } - break; - case FLOAT: - cmp_floats: - /* TODO: Add algebraic reductions for floats */ - switch (op) { - case OADD: - aux.u.f = ls->u.f + rs->u.f; - break; - case OSUB: - aux.u.f = ls->u.f - rs->u.f; - break; - case OMUL: - aux.u.f = ls->u.f * rs->u.f; - break; - case ODIV: - if (rs->u.f == 0.0) - goto division_by_0; - aux.u.f = ls->u.f / rs->u.f; - break; - case OLT: - aux.u.i = ls->u.f < rs->u.f; - break; - case OGT: - aux.u.i = ls->u.f > rs->u.f; - break; - case OGE: - aux.u.i = ls->u.f >= rs->u.f; - break; - case OLE: - aux.u.i = ls->u.f <= rs->u.f; - break; - case OEQ: - aux.u.i = ls->u.f == rs->u.f; - break; - case ONE: - aux.u.i = ls->u.f != rs->u.f; - break; - } - break; - default: - goto no_simplify; - } - - sym = newsym(NS_IDEN); - sym->type = tp; - sym->u = aux.u; - return constnode(sym); - -division_by_0: - warn("division by 0"); - -no_simplify: - return node(op, tp, lp, rp); -} - -#define UFOLDINT(sym, ls, op) (((sym)->type->sign) ? \ - ((sym)->u.i = (op (ls)->u.i)) : \ - ((sym)->u.u = (op (ls)->u.u))) - -static Node * -usimplify(unsigned char op, Type *tp, Node *np) -{ - Symbol *sym, *ns, aux; - - if (!np->constant) - goto no_simplify; - ns = np->sym; - aux.type = tp; - - switch (tp->op) { - case INT: - switch (op) { - case ONEG: - UFOLDINT(&aux, ns, -); - break; - case OCPL: - UFOLDINT(&aux, ns, ~); - break; - default: - goto no_simplify; - } - break; - case FLOAT: - if (op != ONEG) - goto no_simplify; - aux.u.f = -ns->u.f; - break; - default: - goto no_simplify; - } - - sym = newsym(NS_IDEN); - sym->type = tp; - sym->u = aux.u; - return constnode(sym); - -no_simplify: - return node(op, tp, np, NULL); -} - static Node * promote(Node *np) { @@ -423,54 +147,6 @@ integeruop(char op, Node *np) return usimplify(op, np->type, np); } -/* TODO: check validity of types */ - -static Node * -constconv(Node *np, Type *newtp) -{ - Type *oldtp = np->type; - Symbol aux, *sym, *osym = np->sym; - - switch (newtp->op) { - case PTR: - case INT: - case ENUM: - switch (oldtp->op) { - case PTR: - case INT: - case ENUM: - if (newtp->sign == oldtp->sign) - aux.u = osym->u; - if (newtp->sign && !oldtp->sign) - aux.u.i = osym->u.u; - else if (!newtp->sign && oldtp->sign) - aux.u.u = osym->u.u; - break; - case FLOAT: - if (newtp->sign) - aux.u.i = osym->u.f; - else - aux.u.u = osym->u.f; - break; - default: - return NULL; - } - break; - case FLOAT: - aux.u.f = (oldtp->sign) ? osym->u.i : osym->u.u; - break; - default: - return NULL; - } - - sym = newsym(NS_IDEN); - np->type = sym->type = newtp; - np->sym = sym; - sym->u = aux.u; - - return np; -} - /* * Convert a Node to a type */ diff --git a/cc1/fold.c b/cc1/fold.c @@ -0,0 +1,333 @@ + +#include <stdio.h> + +#include "../inc/cc.h" +#include "cc1.h" + + +#define SYMICMP(sym, val) (((sym)->type->sign) ? \ + (sym)->u.i == (val) : (sym)->u.u == (val)) + +#define FOLDINT(sym, ls, rs, op) (((sym)->type->sign) ? \ + ((sym)->u.i = ((ls)->u.i op (rs)->u.i)) : \ + ((sym)->u.u = ((ls)->u.u op (rs)->u.u))) + +#define CMPISYM(sym, ls, rs, op) (((sym)->type->sign) ? \ + ((ls)->u.i op (rs)->u.i) : ((ls)->u.u op (rs)->u.u)) + +Node * +simplify(unsigned char op, Type *tp, Node *lp, Node *rp) +{ + Symbol *sym, *ls, *rs, aux; + int iszero, isone, noconst = 0; + + if (!lp->constant && !rp->constant) + goto no_simplify; + if (!rp->constant) { + Node *np; + np = lp; + lp = rp; + rp = np; + } + if (!lp->constant) + noconst = 1; + + ls = lp->sym, rs = rp->sym; + aux.type = tp; + + /* TODO: Add overflow checkings */ + + if (isnodecmp(op)) { + /* + * Comparision nodes have integer type + * but the operands can have different + * type. + */ + switch (BTYPE(lp)) { + case INT: goto cmp_integers; + case FLOAT: goto cmp_floats; + default: goto no_simplify; + } + } + + switch (tp->op) { + case PTR: + case INT: + cmp_integers: + iszero = SYMICMP(rs, 0); + isone = SYMICMP(rs, 1); + switch (op) { + case OADD: + if (iszero) + return lp; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, +); + break; + case OSUB: + if (iszero) + return lp; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, -); + break; + case OMUL: + if (isone) + return lp; + if (iszero) + return constnode(zero); + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, *); + break; + case ODIV: + if (isone) + return lp; + if (iszero) + goto division_by_0; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, /); + break; + case OMOD: + if (iszero) + goto division_by_0; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, %); + break; + case OSHL: + if (iszero) + return lp; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, <<); + break; + case OSHR: + if (iszero) + return lp; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, >>); + break; + case OBAND: + if (SYMICMP(rs, ~0)) + return lp; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, &); + break; + case OBXOR: + if (iszero) + return lp; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, ^); + break; + case OBOR: + if (iszero) + return lp; + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, |); + break; + case OAND: + if (!iszero) + return lp; + /* TODO: What happens with something like f(0) && 0? */ + if (noconst) + goto no_simplify; + FOLDINT(&aux, ls, rs, &&); + break; + case OOR: + if (iszero) + return lp; + if (noconst) + goto no_simplify; + /* TODO: What happens with something like f(0) || 1? */ + FOLDINT(&aux, ls, rs, ||); + break; + case OLT: + /* TODO: what happens with signess? */ + if (noconst) + goto no_simplify; + aux.u.i = CMPISYM(&aux, ls, rs, <); + break; + case OGT: + /* TODO: what happens with signess? */ + if (noconst) + goto no_simplify; + aux.u.i = CMPISYM(&aux, ls, rs, >); + break; + case OGE: + /* TODO: what happens with signess? */ + if (noconst) + goto no_simplify; + aux.u.i = CMPISYM(&aux, ls, rs, >=); + break; + case OLE: + /* TODO: what happens with signess? */ + if (noconst) + goto no_simplify; + aux.u.i = CMPISYM(&aux, ls, rs, <=); + break; + case OEQ: + /* TODO: what happens with signess? */ + if (noconst) + goto no_simplify; + aux.u.i = CMPISYM(&aux, ls, rs, ==); + break; + case ONE: + /* TODO: what happens with signess? */ + if (noconst) + goto no_simplify; + aux.u.i = CMPISYM(&aux, ls, rs, !=); + break; + } + break; + case FLOAT: + cmp_floats: + /* TODO: Add algebraic reductions for floats */ + switch (op) { + case OADD: + aux.u.f = ls->u.f + rs->u.f; + break; + case OSUB: + aux.u.f = ls->u.f - rs->u.f; + break; + case OMUL: + aux.u.f = ls->u.f * rs->u.f; + break; + case ODIV: + if (rs->u.f == 0.0) + goto division_by_0; + aux.u.f = ls->u.f / rs->u.f; + break; + case OLT: + aux.u.i = ls->u.f < rs->u.f; + break; + case OGT: + aux.u.i = ls->u.f > rs->u.f; + break; + case OGE: + aux.u.i = ls->u.f >= rs->u.f; + break; + case OLE: + aux.u.i = ls->u.f <= rs->u.f; + break; + case OEQ: + aux.u.i = ls->u.f == rs->u.f; + break; + case ONE: + aux.u.i = ls->u.f != rs->u.f; + break; + } + break; + default: + goto no_simplify; + } + + sym = newsym(NS_IDEN); + sym->type = tp; + sym->u = aux.u; + return constnode(sym); + +division_by_0: + warn("division by 0"); + +no_simplify: + return node(op, tp, lp, rp); +} + +#define UFOLDINT(sym, ls, op) (((sym)->type->sign) ? \ + ((sym)->u.i = (op (ls)->u.i)) : \ + ((sym)->u.u = (op (ls)->u.u))) + +Node * +usimplify(unsigned char op, Type *tp, Node *np) +{ + Symbol *sym, *ns, aux; + + if (!np->constant) + goto no_simplify; + ns = np->sym; + aux.type = tp; + + switch (tp->op) { + case INT: + switch (op) { + case ONEG: + UFOLDINT(&aux, ns, -); + break; + case OCPL: + UFOLDINT(&aux, ns, ~); + break; + default: + goto no_simplify; + } + break; + case FLOAT: + if (op != ONEG) + goto no_simplify; + aux.u.f = -ns->u.f; + break; + default: + goto no_simplify; + } + + sym = newsym(NS_IDEN); + sym->type = tp; + sym->u = aux.u; + return constnode(sym); + +no_simplify: + return node(op, tp, np, NULL); +} + +/* TODO: check validity of types */ + +Node * +constconv(Node *np, Type *newtp) +{ + Type *oldtp = np->type; + Symbol aux, *sym, *osym = np->sym; + + switch (newtp->op) { + case PTR: + case INT: + case ENUM: + switch (oldtp->op) { + case PTR: + case INT: + case ENUM: + if (newtp->sign == oldtp->sign) + aux.u = osym->u; + if (newtp->sign && !oldtp->sign) + aux.u.i = osym->u.u; + else if (!newtp->sign && oldtp->sign) + aux.u.u = osym->u.u; + break; + case FLOAT: + if (newtp->sign) + aux.u.i = osym->u.f; + else + aux.u.u = osym->u.f; + break; + default: + return NULL; + } + break; + case FLOAT: + aux.u.f = (oldtp->sign) ? osym->u.i : osym->u.u; + break; + default: + return NULL; + } + + sym = newsym(NS_IDEN); + np->type = sym->type = newtp; + np->sym = sym; + sym->u = aux.u; + + return np; +}