arm64-gen: fix 16-byte alignment for variadic arguments on stack

According to AAPCS64, when an argument requires 16-byte alignment
and is passed on the stack, the stack address must be rounded up
to the next 16-byte boundary.

TCC previously failed to perform this alignment check in gen_va_arg,
leading to data corruption when a 16-byte aligned argument followed
an 8-byte argument on the stack.

Note: This issue is most prominent on Mach-O/Apple Silicon where
variadic arguments are passed entirely on the stack. Testing shows
this fix resolves the failure on macOS while remaining compatible
with Linux/ARM64 (e.g., Raspberry Pi).

Modified gen_va_arg to perform a round-up (addr + 15) & ~15 when
align == 16.
This commit is contained in:
Dylan Fei
2025-12-29 00:57:35 +08:00
parent b8513fe895
commit 5ce2c4b454

View File

@@ -1355,6 +1355,10 @@ ST_FUNC void gen_va_arg(CType *t)
o(0x540000ad); // b.le .+20 o(0x540000ad); // b.le .+20
#endif #endif
o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack
if (align == 16) {
o(0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15
o(0x927cec00 | r1 | r1 << 5); // and x(r1),x(r1),#-16
}
o(0x9100001e | r1 << 5 | n << 10); // add x30,x(r1),#(n) o(0x9100001e | r1 << 5 | n << 10); // add x30,x(r1),#(n)
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
#if !defined(TCC_TARGET_MACHO) #if !defined(TCC_TARGET_MACHO)