scc

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

commit 153d5c396bcf4e67cb2937f06f59c6346b57c4bf
parent 5a05103353eb4b3c5fa387cfb287b781fd06359b
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon,  7 Sep 2015 23:27:58 +0200

Extend sign in constant casts

Since we are doing all the operations in bigger integer types,
we need to operate over quantities when we deal with signed types,
so it means that we have to do sign extension when the higher
bit of the result is 1.

Diffstat:
cc1/fold.c | 30++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/cc1/fold.c b/cc1/fold.c @@ -498,7 +498,7 @@ simplify(int op, Type *tp, Node *lp, Node *rp) Node * castcode(Node *np, Type *newtp) { - TUINT mask; + TUINT negmask, mask, u; Type *oldtp = np->type; Symbol aux, *sym, *osym = np->sym; @@ -509,33 +509,31 @@ castcode(Node *np, Type *newtp) case PTR: case INT: case ENUM: - mask = ones(newtp->size); 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 & mask; - else if (!newtp->sign && oldtp->sign) - aux.u.u = osym->u.u & mask; + u = (oldtp->sign) ? osym->u.i : osym->u.u; break; case FLOAT: - if (newtp->sign) { - aux.u.i = osym->u.f; - aux.u.i &= mask; - } else { - aux.u.u = osym->u.f; - aux.u.u &= mask; - } + u = osym->u.f; break; default: goto noconstant; } + mask = ones(newtp->size); + if (newtp->sign) { + negmask = ~mask; + u &= mask; + if (u & (negmask >> 1) & mask) + u |= negmask; + aux.u.i = u; + } else { + aux.u.u = u & mask; + } break; case FLOAT: - /* FIXME: The cast can be from another floar type */ + /* FIXME: The cast can be from another float type */ aux.u.f = (oldtp->sign) ? osym->u.i : osym->u.u; break; default: