@@ -47,7 +47,8 @@ use std::str::FromStr;
4747use std:: { fmt, io} ;
4848
4949use rustc_abi:: {
50- Align , CanonAbi , Endian , ExternAbi , Integer , Size , TargetDataLayout , TargetDataLayoutError ,
50+ Align , CVariadicStatus , CanonAbi , Endian , ExternAbi , Integer , Size , TargetDataLayout ,
51+ TargetDataLayoutError ,
5152} ;
5253use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
5354use rustc_error_messages:: { DiagArgValue , IntoDiagArg , into_diag_arg_using_display} ;
@@ -2208,30 +2209,54 @@ impl Target {
22082209 Ok ( dl)
22092210 }
22102211
2211- pub fn supports_c_variadic_definitions ( & self ) -> bool {
2212+ pub fn supports_c_variadic_definitions ( & self ) -> CVariadicStatus {
22122213 use Arch :: * ;
22132214
22142215 match self . arch {
2216+ // These targets just inherently do not support c-variadic definitions.
2217+ Bpf | SpirV => CVariadicStatus :: NotSupported ,
2218+
22152219 // The c-variadic ABI for this target may change in the future, per this comment in
22162220 // clang:
22172221 //
22182222 // > To be compatible with GCC's behaviors, we force arguments with
22192223 // > 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`,
22202224 // > `unsigned long long` and `double` to have 4-byte alignment. This
22212225 // > behavior may be changed when RV32E/ILP32E is ratified.
2222- RiscV32 if self . llvm_abiname == LlvmAbi :: Ilp32e => false ,
2223-
2224- // These targets just do not support c-variadic definitions.
2225- Bpf | SpirV => false ,
2226+ RiscV32 if self . llvm_abiname == LlvmAbi :: Ilp32e => {
2227+ CVariadicStatus :: Unstable { feature : sym:: c_variadic_experimental_arch }
2228+ }
22262229
22272230 // We don't know how c-variadics work for this target. Using the default LLVM
2228- // fallback implementation may work , but just to be safe we disallow this .
2229- Other ( _) => false ,
2231+ // fallback implementation probably works , but we can't guarantee it .
2232+ Other ( _) => CVariadicStatus :: Unstable { feature : sym :: c_variadic_experimental_arch } ,
22302233
2231- AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64
2232- | M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC
2233- | PowerPC64 | RiscV32 | RiscV64 | S390x | Sparc | Sparc64 | Wasm32 | Wasm64 | X86
2234- | X86_64 | Xtensa => true ,
2234+ // These targets require more testing before we commit to c-variadic definitions
2235+ // being stable.
2236+ //
2237+ // To stabilize c-variadic functions for one of these targets, the following
2238+ // requirements must be met:
2239+ //
2240+ // - Check that `core::ffi::VaArgSafe` is (un)implemented for all the correct types.
2241+ // - Add an assembly test to `tests/assembly-llvm/c-variadic` that tests the assembly
2242+ // for all implementers of `VaArgSafe`. The generated assembly should either match
2243+ // `clang`, or we should understand and document why it deviates.
2244+ // - Ensure that `va_arg` is implemented in rustc. For stable targets we don't rely on
2245+ // the LLVM implementation, it has historically caused miscompilations.
2246+ // - The `tests/ui/c-variadic/roundtrip.rs` test must pass for the target. It may
2247+ // need slight modifications for embedded targets, that's fine.
2248+ // - Check that calling c-variadic functions defined in Rust can be called from C.
2249+ // For most targets `tests/run-make/c-link-to-rust-va-list-fn` can be used here.
2250+ // For no_std targets a manual setup may be needed.
2251+ Sparc | Avr | M68k | Msp430 => {
2252+ CVariadicStatus :: Unstable { feature : sym:: c_variadic_experimental_arch }
2253+ }
2254+
2255+ AArch64 | AmdGpu | Arm | Arm64EC | CSky | Hexagon | LoongArch32 | LoongArch64
2256+ | Mips | Mips32r6 | Mips64 | Mips64r6 | Nvptx64 | PowerPC | PowerPC64 | RiscV32
2257+ | RiscV64 | S390x | Sparc64 | Wasm32 | Wasm64 | X86 | X86_64 | Xtensa => {
2258+ CVariadicStatus :: Stable
2259+ }
22352260 }
22362261 }
22372262}
0 commit comments