Rollup merge of #152935 - folkertdev:c-variadic-disallow, r=tgross35

c-variadic: error when we can't guarantee that the backend does the right thing

tracking issue: https://github.com/rust-lang/rust/issues/44930
r? workingjubilee

as discussed in [#t-lang > stabilizing `c_variadic`](https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/stabilizing.20.60c_variadic.60/with/574691397), display an error when we can't guarantee that the codegen backend (only LLVM is supported at the moment) does the right thing.
This commit is contained in:
Yukang
2026-04-01 10:43:55 +08:00
committed by GitHub
3 changed files with 32 additions and 22 deletions
@@ -762,7 +762,7 @@ fn check_c_variadic_type(&self, fk: FnKind<'a>, attrs: &'a AttrVec) {
match fn_ctxt {
FnCtxt::Foreign => return,
FnCtxt::Free | FnCtxt::Assoc(_) => {
if !self.sess.target.arch.supports_c_variadic_definitions() {
if !self.sess.target.supports_c_variadic_definitions() {
self.dcx().emit_err(errors::CVariadicNotSupported {
variadic_span: variadic_param.span,
target: &*self.sess.target.llvm_target,
+4 -3
View File
@@ -1186,9 +1186,10 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
// Clang uses the LLVM implementation for these architectures.
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
}
Arch::Other(_) => {
// For custom targets, use the LLVM va_arg instruction as a fallback.
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
Arch::Other(ref arch) => {
// Just to be safe we error out explicitly here, instead of crossing our fingers that
// the default LLVM implementation has the correct behavior for this target.
bug!("c-variadic functions are not currently implemented for custom target {arch}")
}
}
}
+27 -18
View File
@@ -1952,24 +1952,6 @@ pub fn desc_symbol(&self) -> Symbol {
}
}
pub fn supports_c_variadic_definitions(&self) -> bool {
use Arch::*;
match self {
// These targets just do not support c-variadic definitions.
Bpf | SpirV => false,
// We don't know if the target supports c-variadic definitions, but we don't want
// to needlessly restrict custom target.json configurations.
Other(_) => true,
AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64
| M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC
| PowerPC64 | RiscV32 | RiscV64 | S390x | Sparc | Sparc64 | Wasm32 | Wasm64 | X86
| X86_64 | Xtensa => true,
}
}
/// Whether `#[rustc_scalable_vector]` is supported for a target architecture
pub fn supports_scalable_vectors(&self) -> bool {
use Arch::*;
@@ -2214,6 +2196,33 @@ pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErro
Ok(dl)
}
pub fn supports_c_variadic_definitions(&self) -> bool {
use Arch::*;
match self.arch {
// The c-variadic ABI for this target may change in the future, per this comment in
// clang:
//
// > To be compatible with GCC's behaviors, we force arguments with
// > 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`,
// > `unsigned long long` and `double` to have 4-byte alignment. This
// > behavior may be changed when RV32E/ILP32E is ratified.
RiscV32 if self.llvm_abiname == LlvmAbi::Ilp32e => false,
// These targets just do not support c-variadic definitions.
Bpf | SpirV => false,
// We don't know how c-variadics work for this target. Using the default LLVM
// fallback implementation may work, but just to be safe we disallow this.
Other(_) => false,
AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64
| M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC
| PowerPC64 | RiscV32 | RiscV64 | S390x | Sparc | Sparc64 | Wasm32 | Wasm64 | X86
| X86_64 | Xtensa => true,
}
}
}
pub trait HasTargetSpec {