diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-12-12 20:58:59 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-12-12 20:58:59 +0000 |
commit | e33798c7e0333e6b8c39be76c7b143834d81b81e (patch) | |
tree | 55c2fff71f6852064551bc15d1733f1c50114d23 | |
parent | e74a87d537dfd2ed817ba94314df7c517b51d65a (diff) |
cc: don't rearrange constant scaling across unsigned casts
On 64-bit platforms, when the index being 32-bit unsigned,
any calculation there must be done modulo 2^32,
but rearranging the factors into the address calculation
is done in signed 64-bits yielding the wrong index.
-rw-r--r-- | sys/src/cmd/cc/scon.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/sys/src/cmd/cc/scon.c b/sys/src/cmd/cc/scon.c index f0c2bd139..32ba87cbe 100644 --- a/sys/src/cmd/cc/scon.c +++ b/sys/src/cmd/cc/scon.c @@ -587,8 +587,16 @@ addo(Node *n) switch(n->op) { case OCAST: - if(nilcast(n->left->type, n->type)) - return 1; + if(nilcast(n->left->type, n->type)){ + /* + * must not cross casts from unsigned + * when the modulus changes to handle + * overflow correctly. + */ + if(!typeu[n->left->type->etype] + || ewidth[n->left->type->etype] == ewidth[n->type->etype]) + return 1; + } break; case ONEG: |