Skip to content

Commit 3b96e18

Browse files
committed
c-variadic: error when we can't guarantee that the backend does the right thing
1 parent c043085 commit 3b96e18

3 files changed

Lines changed: 19 additions & 8 deletions

File tree

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,8 @@ impl<'a> AstValidator<'a> {
761761
match fn_ctxt {
762762
FnCtxt::Foreign => return,
763763
FnCtxt::Free | FnCtxt::Assoc(_) => {
764-
if !self.sess.target.arch.supports_c_variadic_definitions() {
764+
let target = &self.sess.target;
765+
if !target.arch.supports_c_variadic_definitions(&target.abi) {
765766
self.dcx().emit_err(errors::CVariadicNotSupported {
766767
variadic_span: variadic_param.span,
767768
target: &*self.sess.target.llvm_target,

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,9 +1186,10 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
11861186
// Clang uses the LLVM implementation for these architectures.
11871187
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
11881188
}
1189-
Arch::Other(_) => {
1190-
// For custom targets, use the LLVM va_arg instruction as a fallback.
1191-
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
1189+
Arch::Other(ref arch) => {
1190+
// Just to be safe we error out explicitly here, instead of crossing our fingers that
1191+
// the default LLVM implementation has the correct behavior for this target.
1192+
bug!("c-variadic functions are not currently implemented for custom target {arch}")
11921193
}
11931194
}
11941195
}

compiler/rustc_target/src/spec/mod.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,16 +1939,25 @@ impl Arch {
19391939
}
19401940
}
19411941

1942-
pub fn supports_c_variadic_definitions(&self) -> bool {
1942+
pub fn supports_c_variadic_definitions(&self, abi: &Abi) -> bool {
19431943
use Arch::*;
19441944

19451945
match self {
1946+
// The c-variadic ABI for this target may change in the future, per this comment in
1947+
// clang:
1948+
//
1949+
// > To be compatible with GCC's behaviors, we force arguments with
1950+
// > 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`,
1951+
// > `unsigned long long` and `double` to have 4-byte alignment. This
1952+
// > behavior may be changed when RV32E/ILP32E is ratified.
1953+
RiscV32 if *abi == Abi::Ilp32e => false,
1954+
19461955
// These targets just do not support c-variadic definitions.
19471956
Bpf | SpirV => false,
19481957

1949-
// We don't know if the target supports c-variadic definitions, but we don't want
1950-
// to needlessly restrict custom target.json configurations.
1951-
Other(_) => true,
1958+
// We don't know how c-variadics work for this target. Using the default LLVM
1959+
// fallback implementation may work, but just to be safe we disallow this.
1960+
Other(_) => false,
19521961

19531962
AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64
19541963
| M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC

0 commit comments

Comments
 (0)