Thank you for your review and guidance. As you suggested, I have also fixed the same issue in riscv64-gen.c. This new patch includes the fix for both aarch64 and riscv64. Please review.
Thanks, Dylan Fei ----------- From 11118be71770cefc3bf971798ac610dd2b4df807 Mon Sep 17 00:00:00 2001 From: Dylan Fei <[email protected]> Date: Tue, 23 Dec 2025 15:54:35 +0800 Subject: [PATCH] Fix pointer difference issue in aarch64/riscv64 When calculating the difference between two pointers (TOK_PDIV), the AArch64 and RISC-V64 backends used unsigned division instructions (udiv/divu). This patch moves TOK_PDIV to use signed division instructions (sdiv/div) for both backends, ensuring correct behavior as per the C standard. --- arm64-gen.c | 2 +- riscv64-gen.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arm64-gen.c b/arm64-gen.c index 01ea3909..2038aeba 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -1756,6 +1756,7 @@ static void arm64_gen_opil(int op, uint32_t l) o(0x4b000000 | l << 31 | x | a << 5 | b << 16); // sub break; case '/': + case TOK_PDIV: o(0x1ac00c00 | l << 31 | x | a << 5 | b << 16); // sdiv break; case '^': @@ -1798,7 +1799,6 @@ static void arm64_gen_opil(int op, uint32_t l) o(0x1ac02400 | l << 31 | x | a << 5 | b << 16); // lsr break; case TOK_UDIV: - case TOK_PDIV: o(0x1ac00800 | l << 31 | x | a << 5 | b << 16); // udiv break; case TOK_UGE: diff --git a/riscv64-gen.c b/riscv64-gen.c index e03d6e42..19c76682 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -1110,6 +1110,7 @@ static void gen_opil(int op, int ll) ER(0x33 | ll, 0, d, a, b, 1); // mul d, a, b break; case '/': + case TOK_PDIV: ER(0x33 | ll, 4, d, a, b, 1); // div d, a, b break; case '&': @@ -1127,7 +1128,6 @@ static void gen_opil(int op, int ll) case TOK_UMOD: ER(0x33 | ll, 7, d, a, b, 1); // remu d, a, b break; - case TOK_PDIV: case TOK_UDIV: ER(0x33 | ll, 5, d, a, b, 1); // divu d, a, b break; -- 2.51.2 On Mon, Dec 22, 2025 at 8:18 PM Herman ten Brugge via Tinycc-devel <[email protected]> wrote: > > On 12/21/25 15:10, Dylan Fei wrote: > > Hi TCC developers, > > > > A critical and basic bug is found in the AArch64 backend > > (aarch64-gen.c) regarding pointer difference calculation. > > > > The Issue: > > When calculating the difference between two pointers (TOK_PDIV), the > > AArch64 backend currently uses the udiv (Unsigned Divide) instruction. > > However, the result of pointer subtraction (ptrdiff_t) is signed. This > > causes incorrect results when the difference is negative (i.e., > > low_addr - high_addr) and the structure size is not a power of 2 > > (which prevents bitwise optimization). > > > > Reproduction Code: > > > > #include <stdio.h> > > > > struct Node { > > long a; > > long b; > > long c; > > }; // sizeof(struct Node) == 24 > > > > int main() { > > struct Node data[2]; > > struct Node *f = &data[0]; > > struct Node *mp = &data[1]; > > > > // On aarch64, this should print -1, but prints -1431655767 due to udiv > > printf("%d\n", (int)(f - mp)); > > > > return 0; > > } > > > > > > The Fix: > > In aarch64-gen.c, TOK_PDIV is currently grouped with TOK_UDIV. It > > should be grouped with the signed division operator /. > > > > Here is the patch: > > > > diff --git a/arm64-gen.c b/arm64-gen.c > > index 01ea3909..2038aeba 100644 > > --- a/arm64-gen.c > > +++ b/arm64-gen.c > > @@ -1756,6 +1756,7 @@ static void arm64_gen_opil(int op, uint32_t l) > > o(0x4b000000 | l << 31 | x | a << 5 | b << 16); // sub > > break; > > case '/': > > + case TOK_PDIV: > > o(0x1ac00c00 | l << 31 | x | a << 5 | b << 16); // sdiv > > break; > > case '^': > > @@ -1798,7 +1799,6 @@ static void arm64_gen_opil(int op, uint32_t l) > > o(0x1ac02400 | l << 31 | x | a << 5 | b << 16); // lsr > > break; > > case TOK_UDIV: > > - case TOK_PDIV: > > o(0x1ac00800 | l << 31 | x | a << 5 | b << 16); // udiv > > break; > > case TOK_UGE: > > > > > > This change fixes the issue on AArch64 and produces the correct signed > > result. > This is ok. You can apply it. > I see that riscv64-gen.c has the same problem. Can you change that as well? > The other targets seem ok. > > Herman > > > _______________________________________________ > Tinycc-devel mailing list > [email protected] > https://lists.nongnu.org/mailman/listinfo/tinycc-devel _______________________________________________ Tinycc-devel mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/tinycc-devel
