diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index a64452dbc5a7e..8d2a504d4877b 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -1233,6 +1233,28 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( // sparc64 is a big-endian target and stores variable arguments right-adjusted. ForceRightAdjust::Yes, ), + Arch::Sparc => { + std::assert_matches!(stability, CVariadicStatus::Unstable { .. }); + + // f128 is passed indirectly. + let pass_mode = match layout.layout.backend_repr() { + BackendRepr::Scalar(scalar) => match scalar.primitive() { + Primitive::Float(Float::F128) => PassMode::Indirect, + _ => PassMode::Direct, + }, + _ => PassMode::Direct, + }; + + emit_ptr_va_arg( + bx, + addr, + target_ty, + pass_mode, + SlotSize::Bytes4, + AllowHigherAlign::No, + ForceRightAdjust::Yes, + ) + } Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => emit_ptr_va_arg( bx, addr, @@ -1256,7 +1278,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::Bpf => bug!("bpf does not support c-variadic functions"), Arch::SpirV => bug!("spirv does not support c-variadic functions"), - Arch::Sparc | Arch::Avr | Arch::M68k | Arch::Msp430 => { + Arch::Avr | Arch::M68k | Arch::Msp430 => { std::assert_matches!(stability, CVariadicStatus::Unstable { .. }); // Clang uses the LLVM implementation for these architectures. diff --git a/tests/assembly-llvm/c-variadic/sparc.rs b/tests/assembly-llvm/c-variadic/sparc.rs index f3a86ed8a1a6c..78ce38ac3480e 100644 --- a/tests/assembly-llvm/c-variadic/sparc.rs +++ b/tests/assembly-llvm/c-variadic/sparc.rs @@ -90,14 +90,17 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // CHECK-LABEL: read_i64 // // SPARC: ld [%o0], %o1 - // SPARC-NEXT: add %o1, 4, %o2 + // SPARC-NEXT: add %o1, 8, %o2 // SPARC-NEXT: st %o2, [%o0] - // SPARC-NEXT: ld [%o1], %o2 - // SPARC-NEXT: add %o1, 8, %o3 - // SPARC-NEXT: st %o3, [%o0] - // SPARC-NEXT: ld [%o1+4], %o1 + // SPARC-NEXT: ld [%o1+4], %o0 + // SPARC-NEXT: add %sp, 96, %o2 + // SPARC-NEXT: or %o2, 4, %o2 + // SPARC-NEXT: st %o0, [%o2] + // SPARC-NEXT: ld [%o1], %o0 + // SPARC-NEXT: st %o0, [%sp+96] + // SPARC-NEXT: ldd [%sp+96], %o0 // SPARC-NEXT: retl - // SPARC-NEXT: mov %o2, %o0 + // SPARC-NEXT: add %sp, 104, %sp // // SPARC64: ldx [%o0], %o1 // SPARC64-NEXT: add %o1, 8, %o2 diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs index 6999f7eeb5a5d..37110e75f4779 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs @@ -1,5 +1,5 @@ #![crate_type = "staticlib"] -#![feature(c_variadic_int128)] +#![feature(c_variadic_int128, c_variadic_experimental_arch)] use core::ffi::{CStr, VaList, c_char, c_double, c_int, c_long, c_longlong};