summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2023-12-12 20:58:59 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2023-12-12 20:58:59 +0000
commite33798c7e0333e6b8c39be76c7b143834d81b81e (patch)
tree55c2fff71f6852064551bc15d1733f1c50114d23
parente74a87d537dfd2ed817ba94314df7c517b51d65a (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.c12
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: