scc

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

commit ad2d3ea7a4b95be09db3643e96b9e485e3296e81
parent 486b07bfc9005abb6f11749d48d07fccd7118ef2
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 29 Jul 2015 09:35:00 +0200

Add compiler time conversions

Diffstat:
Mcc1/expr.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 60 insertions(+), 10 deletions(-)

diff --git a/cc1/expr.c b/cc1/expr.c @@ -327,21 +327,71 @@ decay(Node *np) return node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL); } +static Node * +constconv(Node *np, Type *newtp) +{ + Type *oldtp = np->type; + Symbol aux, *sym, *osym = np->sym; + + switch (newtp->op) { + case INT: + case ENUM: + switch (oldtp->op) { + 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) ? sym->u.i : sym->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 */ Node * -convert(Node *np, Type *tp, char iscast) +convert(Node *np, Type *newtp, char iscast) { - if (eqtype(np->type, tp)) + Type *oldtp = np->type; + Node *p; + + if (eqtype(newtp, oldtp)) return np; - switch (BTYPE(np)) { + if (np->constant && (p = constconv(np, newtp)) != NULL) + return p; + + switch (oldtp->op) { case ENUM: case INT: case FLOAT: - switch (tp->op) { + switch (newtp->op) { case PTR: - if (!iscast || BTYPE(np) == FLOAT) + if (!iscast || oldtp->op == FLOAT) return NULL; /* PASSTHROUGH */ case INT: @@ -354,7 +404,7 @@ convert(Node *np, Type *tp, char iscast) } break; case PTR: - switch (tp->op) { + switch (newtp->op) { case ENUM: /* TODO: allow p = 0 */ case INT: case VOID: @@ -363,14 +413,14 @@ convert(Node *np, Type *tp, char iscast) break; case PTR: if (iscast || - tp == pvoidtype || - np->type == pvoidtype) { + newtp == pvoidtype || + oldtp == pvoidtype) { /* TODO: * we assume conversion between pointers * do not need any operation, but due to * alignment problems that may be false */ - np->type = tp; + np->type = newtp; return np; } default: @@ -379,7 +429,7 @@ convert(Node *np, Type *tp, char iscast) default: return NULL; } - return node(OCAST, tp, np, NULL); + return node(OCAST, newtp, np, NULL); } static Node *