ref: 153d5c396bcf4e67cb2937f06f59c6346b57c4bf
parent: 5a05103353eb4b3c5fa387cfb287b781fd06359b
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Sep 7 19:27:58 EDT 2015
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.
--- a/cc1/fold.c
+++ b/cc1/fold.c
@@ -498,7 +498,7 @@
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 @@
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: