Bug
In compiler/rustc_codegen_llvm/src/va_arg.rs:256, the AAPCS64 va_arg on-stack path passes ForceRightAdjust::No, skipping the big-endian right-adjustment for values smaller than the 8-byte stack slot.
The register path (lines 238-242) correctly applies this adjustment, and other big-endian targets (PPC64, Sparc64, MIPS) all use ForceRightAdjust::Yes for their on-stack paths.
Per the AAPCS64 spec, when a non-aggregate argument is smaller than its stack slot, on big-endian targets the value is right-adjusted within the 8-byte slot. Clang implements this explicitly in EmitAAPCSVAArg.
Impact
On big-endian AArch64 targets (aarch64_be-unknown-linux-gnu, etc.), va_arg::<i32>() and va_arg::<u32>() read the wrong 4 bytes from an 8-byte stack slot when the argument has spilled past the register save area (more than 8 integer varargs). This is silent data corruption.
Fix
Change ForceRightAdjust::No to ForceRightAdjust::Yes on line 256.
Bug
In
compiler/rustc_codegen_llvm/src/va_arg.rs:256, the AAPCS64va_argon-stack path passesForceRightAdjust::No, skipping the big-endian right-adjustment for values smaller than the 8-byte stack slot.The register path (lines 238-242) correctly applies this adjustment, and other big-endian targets (PPC64, Sparc64, MIPS) all use
ForceRightAdjust::Yesfor their on-stack paths.Per the AAPCS64 spec, when a non-aggregate argument is smaller than its stack slot, on big-endian targets the value is right-adjusted within the 8-byte slot. Clang implements this explicitly in
EmitAAPCSVAArg.Impact
On big-endian AArch64 targets (
aarch64_be-unknown-linux-gnu, etc.),va_arg::<i32>()andva_arg::<u32>()read the wrong 4 bytes from an 8-byte stack slot when the argument has spilled past the register save area (more than 8 integer varargs). This is silent data corruption.Fix
Change
ForceRightAdjust::NotoForceRightAdjust::Yeson line 256.