Skip to content

Commit c4e3ffd

Browse files
committed
c-variadic: fix i128 argument being misread on aarch64 msvc
1 parent bd41781 commit c4e3ffd

2 files changed

Lines changed: 39 additions & 2 deletions

File tree

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
10981098
target_ty,
10991099
PassMode::Direct,
11001100
SlotSize::Bytes8,
1101-
if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes },
1101+
AllowHigherAlign::Yes,
11021102
ForceRightAdjust::No,
11031103
),
11041104
Arch::AArch64 => emit_aapcs_va_arg(bx, addr, target_ty),

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
//@ add-minicore
22
//@ assembly-output: emit-asm
33
//
4-
//@ revisions: AARCH64_LINUX AARCH64_DARWIN AARCH64_BE ARM64EC_MSVC
4+
//@ revisions: AARCH64_LINUX AARCH64_DARWIN AARCH64_BE AARCH64_MSVC ARM64EC_MSVC
55
//@ [AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu
66
//@ [AARCH64_LINUX] needs-llvm-components: aarch64
77
//@ [AARCH64_BE] compile-flags: -Copt-level=3 --target aarch64_be-unknown-linux-gnu
88
//@ [AARCH64_BE] needs-llvm-components: aarch64
99
//@ [AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin
1010
//@ [AARCH64_DARWIN] needs-llvm-components: aarch64
11+
//@ [AARCH64_MSVC] compile-flags: -Copt-level=3 --target aarch64-pc-windows-msvc
12+
//@ [AARCH64_MSVC] needs-llvm-components: aarch64
1113
//@ [ARM64EC_MSVC] compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc
1214
//@ [ARM64EC_MSVC] needs-llvm-components: aarch64
1315
#![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs)]
@@ -101,6 +103,12 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 {
101103
// AARCH64_DARWIN-NEXT: ldr d0, [x8], #8
102104
// AARCH64_DARWIN-NEXT: str x8, [x0]
103105
// AARCH64_DARWIN-NEXT: ret
106+
107+
// AARCH64_MSVC-LABEL: read_f64:
108+
// AARCH64_MSVC: ldr x8, [x0]
109+
// AARCH64_MSVC-NEXT: ldr d0, [x8], #8
110+
// AARCH64_MSVC-NEXT: str x8, [x0]
111+
// AARCH64_MSVC-NEXT: ret
104112
va_arg(ap)
105113
}
106114

@@ -157,6 +165,13 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 {
157165
// AARCH64_DARWIN-NEXT: str x9, [x0]
158166
// AARCH64_DARWIN-NEXT: mov x0, x8
159167
// AARCH64_DARWIN-NEXT: ret
168+
169+
// AARCH64_MSVC-LABEL: read_i32:
170+
// AARCH64_MSVC: ldr x9, [x0]
171+
// AARCH64_MSVC-NEXT: mov x8, x0
172+
// AARCH64_MSVC-NEXT: ldr w0, [x9], #8
173+
// AARCH64_MSVC-NEXT: str x9, [x8]
174+
// AARCH64_MSVC-NEXT: ret
160175
va_arg(ap)
161176
}
162177

@@ -214,6 +229,13 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 {
214229
// AARCH64_DARWIN-NEXT: str x9, [x0]
215230
// AARCH64_DARWIN-NEXT: mov x0, x8
216231
// AARCH64_DARWIN-NEXT: ret
232+
233+
// AARCH64_MSVC-LABEL: read_i64:
234+
// AARCH64_MSVC: ldr x9, [x0]
235+
// AARCH64_MSVC-NEXT: mov x8, x0
236+
// AARCH64_MSVC-NEXT: ldr x0, [x9], #8
237+
// AARCH64_MSVC-NEXT: str x9, [x8]
238+
// AARCH64_MSVC-NEXT: ret
217239
va_arg(ap)
218240
}
219241

@@ -281,13 +303,28 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 {
281303
// AARCH64_DARWIN-NEXT: str x9, [x0]
282304
// AARCH64_DARWIN-NEXT: mov x0, x8
283305
// AARCH64_DARWIN-NEXT: ret
306+
307+
// NOTE: rustc bumps the alignment to 16, which deviates from clang's va_arg
308+
// but matches MSVC and how clang passes i128 c-variadic arguments.
309+
//
310+
// AARCH64_MSVC-LABEL: read_i128:
311+
// AARCH64_MSVC: ldr x9, [x0]
312+
// AARCH64_MSVC-NEXT: mov x8, x0
313+
// AARCH64_MSVC-NEXT: add x9, x9, #15
314+
// AARCH64_MSVC-NEXT: and x9, x9, #0xfffffffffffffff0
315+
// AARCH64_MSVC-NEXT: mov x10, x9
316+
// AARCH64_MSVC-NEXT: ldr x1, [x9, #8]
317+
// AARCH64_MSVC-NEXT: ldr x0, [x10], #16
318+
// AARCH64_MSVC-NEXT: str x10, [x8]
319+
// AARCH64_MSVC-NEXT: ret
284320
va_arg(ap)
285321
}
286322

287323
#[unsafe(no_mangle)]
288324
unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 {
289325
// AARCH64_LINUX-CHECK: read_ptr = read_i64
290326
// AARCH64_BE-CHECK: read_ptr = read_i64
327+
// AARCH64_MSVC: read_ptr = read_i64
291328
// ARM64EC_MSVC: "#read_ptr" = "#read_i64"
292329
// AARCH64_DARWIN-CHECK: _read_ptr = _read_i64
293330
va_arg(ap)

0 commit comments

Comments
 (0)