Skip to content

Commit f64973c

Browse files
committed
c-variadic: fix i128 argument being misread on arm64ec
1 parent c4e3ffd commit f64973c

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,9 +1087,15 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
10871087
bx,
10881088
addr,
10891089
target_ty,
1090-
PassMode::Direct,
1090+
// MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
1091+
// not 1, 2, 4, or 8 bytes, must be passed by reference."
1092+
if target_ty_size > 8 || !target_ty_size.is_power_of_two() {
1093+
PassMode::Indirect
1094+
} else {
1095+
PassMode::Direct
1096+
},
10911097
SlotSize::Bytes8,
1092-
if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes },
1098+
AllowHigherAlign::No,
10931099
ForceRightAdjust::No,
10941100
),
10951101
Arch::AArch64 if target.is_like_windows || target.is_like_darwin => emit_ptr_va_arg(

tests/assembly-llvm/c-variadic/aarch64.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,13 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 {
287287
// AARCH64_BE-NEXT: ldp x0, x1, [x8]
288288
// AARCH64_BE-NEXT: ret
289289

290+
// NOTE: matches x86_64 Windows: an `i128` is passed indirectly, the slot holds a pointer.
291+
//
290292
// ARM64EC_MSVC-LABEL: read_i128 = "#read_i128"
291293
// ARM64EC_MSVC: ldr x9, [x0]
292-
// ARM64EC_MSVC-NEXT: mov x8, x0
293-
// ARM64EC_MSVC-NEXT: ldp x0, x1, [x9], #16
294-
// ARM64EC_MSVC-NEXT: str x9, [x8]
294+
// ARM64EC_MSVC-NEXT: ldr x10, [x9], #8
295+
// ARM64EC_MSVC-NEXT: str x9, [x0]
296+
// ARM64EC_MSVC-NEXT: ldp x0, x1, [x10]
295297
// ARM64EC_MSVC-NEXT: ret
296298

297299
// AARCH64_DARWIN-LABEL: _read_i128:

0 commit comments

Comments
 (0)