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

Reply via email to