Rollup merge of #144359 - RalfJung:vararg-codegen, r=compiler-errors

add codegen test for variadics

This is a part of https://github.com/rust-lang/rust/pull/144066 that can land without FCP.
This commit is contained in:
Jacob Pratt 2025-07-26 22:42:33 -04:00 committed by GitHub
commit e2c2d1a493
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 110 additions and 59 deletions

View file

@ -0,0 +1,86 @@
//! Test calling variadic functions with various ABIs.
//@ add-core-stubs
//@ compile-flags: -Z merge-functions=disabled
//@ revisions: x86_32 x86_32_win x86_64 aarch64 arm32
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//@[x86_64] needs-llvm-components: x86
//@[x86_32_win] compile-flags: --target i686-pc-windows-msvc
//@[x86_32_win] needs-llvm-components: x86
//@[x86_32] compile-flags: --target i686-unknown-linux-gnu
//@[x86_32] needs-llvm-components: x86
//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
//@[aarch64] needs-llvm-components: aarch64
//@[arm32] compile-flags: --target armv7-unknown-linux-gnueabihf
//@[arm32] needs-llvm-components: arm
#![crate_type = "lib"]
#![feature(no_core)]
#![feature(extended_varargs_abi_support, extern_system_varargs)]
#![no_core]
extern crate minicore;
// CHECK-LABEL: @c
#[unsafe(no_mangle)]
fn c(f: extern "C" fn(i32, ...)) {
// CHECK: call void (i32, ...)
f(22, 44);
}
// CHECK-LABEL: @system
#[unsafe(no_mangle)]
fn system(f: extern "system" fn(i32, ...)) {
// Crucially, this is *always* the C calling convention, even on Windows.
// CHECK: call void (i32, ...)
f(22, 44);
}
// x86_32-LABEL: @cdecl
#[unsafe(no_mangle)]
#[cfg(target_arch = "x86")]
fn cdecl(f: extern "cdecl" fn(i32, ...)) {
// x86_32: call void (i32, ...)
f(22, 44);
}
// x86_64-LABEL: @sysv
#[unsafe(no_mangle)]
#[cfg(target_arch = "x86_64")]
fn sysv(f: extern "sysv64" fn(i32, ...)) {
// x86_64: call x86_64_sysvcc void (i32, ...)
f(22, 44);
}
// x86_64-LABEL: @win
#[unsafe(no_mangle)]
#[cfg(target_arch = "x86_64")]
fn win(f: extern "win64" fn(i32, ...)) {
// x86_64: call win64cc void (i32, ...)
f(22, 44);
}
// CHECK-LABEL: @efiapi
#[unsafe(no_mangle)]
#[cfg(any(
target_arch = "arm",
target_arch = "aarch64",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "x86",
target_arch = "x86_64"
))]
fn efiapi(f: extern "efiapi" fn(i32, ...)) {
// x86_32: call void (i32, ...)
// x86_32_win: call void (i32, ...)
// x86_64: call win64cc void (i32, ...)
// aarch64: call void (i32, ...)
// arm32: call arm_aapcscc void (i32, ...)
f(22, 44);
}
// arm32-LABEL: @aapcs
#[unsafe(no_mangle)]
#[cfg(target_arch = "arm")]
fn aapcs(f: extern "aapcs" fn(i32, ...)) {
// arm32: call arm_aapcscc void (i32, ...)
f(22, 44);
}

View file

@ -12,6 +12,11 @@ extern "stdcall" {
//~^ ERROR: C-variadic functions with the "stdcall" calling convention are not supported
}
fn baz(f: extern "Rust" fn(usize, ...)) {
//~^ ERROR: C-variadic functions with the "Rust" calling convention are not supported
f(22, 44);
}
extern "C" {
fn foo(f: isize, x: u8, ...);
}

View file

@ -4,14 +4,20 @@ error[E0045]: C-variadic functions with the "stdcall" calling convention are not
LL | fn printf(_: *const u8, ...);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error[E0045]: C-variadic functions with the "Rust" calling convention are not supported
--> $DIR/variadic-ffi-1.rs:15:11
|
LL | fn baz(f: extern "Rust" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
--> $DIR/variadic-ffi-1.rs:23:9
--> $DIR/variadic-ffi-1.rs:28:9
|
LL | foo();
| ^^^-- two arguments of type `isize` and `u8` are missing
|
note: function defined here
--> $DIR/variadic-ffi-1.rs:16:8
--> $DIR/variadic-ffi-1.rs:21:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^ - -
@ -21,13 +27,13 @@ LL | foo(/* isize */, /* u8 */);
| +++++++++++++++++++++
error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
--> $DIR/variadic-ffi-1.rs:24:9
--> $DIR/variadic-ffi-1.rs:29:9
|
LL | foo(1);
| ^^^--- argument #2 of type `u8` is missing
|
note: function defined here
--> $DIR/variadic-ffi-1.rs:16:8
--> $DIR/variadic-ffi-1.rs:21:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^ -
@ -37,7 +43,7 @@ LL | foo(1, /* u8 */);
| ++++++++++
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:26:56
--> $DIR/variadic-ffi-1.rs:31:56
|
LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
| ------------------------------------- ^^^ expected non-variadic fn, found variadic function
@ -48,7 +54,7 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:27:54
--> $DIR/variadic-ffi-1.rs:32:54
|
LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar;
| ----------------------------------- ^^^ expected variadic fn, found non-variadic function
@ -59,7 +65,7 @@ LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar;
found fn item `extern "C" fn(_, _) {bar}`
error[E0617]: can't pass `f32` to variadic function
--> $DIR/variadic-ffi-1.rs:29:19
--> $DIR/variadic-ffi-1.rs:34:19
|
LL | foo(1, 2, 3f32);
| ^^^^
@ -70,7 +76,7 @@ LL | foo(1, 2, 3f32 as c_double);
| +++++++++++
error[E0617]: can't pass `bool` to variadic function
--> $DIR/variadic-ffi-1.rs:30:19
--> $DIR/variadic-ffi-1.rs:35:19
|
LL | foo(1, 2, true);
| ^^^^
@ -81,7 +87,7 @@ LL | foo(1, 2, true as c_int);
| ++++++++
error[E0617]: can't pass `i8` to variadic function
--> $DIR/variadic-ffi-1.rs:31:19
--> $DIR/variadic-ffi-1.rs:36:19
|
LL | foo(1, 2, 1i8);
| ^^^
@ -92,7 +98,7 @@ LL | foo(1, 2, 1i8 as c_int);
| ++++++++
error[E0617]: can't pass `u8` to variadic function
--> $DIR/variadic-ffi-1.rs:32:19
--> $DIR/variadic-ffi-1.rs:37:19
|
LL | foo(1, 2, 1u8);
| ^^^
@ -103,7 +109,7 @@ LL | foo(1, 2, 1u8 as c_uint);
| +++++++++
error[E0617]: can't pass `i16` to variadic function
--> $DIR/variadic-ffi-1.rs:33:19
--> $DIR/variadic-ffi-1.rs:38:19
|
LL | foo(1, 2, 1i16);
| ^^^^
@ -114,7 +120,7 @@ LL | foo(1, 2, 1i16 as c_int);
| ++++++++
error[E0617]: can't pass `u16` to variadic function
--> $DIR/variadic-ffi-1.rs:34:19
--> $DIR/variadic-ffi-1.rs:39:19
|
LL | foo(1, 2, 1u16);
| ^^^^
@ -124,7 +130,7 @@ help: cast the value to `c_uint`
LL | foo(1, 2, 1u16 as c_uint);
| +++++++++
error: aborting due to 11 previous errors
error: aborting due to 12 previous errors
Some errors have detailed explanations: E0045, E0060, E0308, E0617.
For more information about an error, try `rustc --explain E0045`.

View file

@ -1,9 +0,0 @@
//@ only-arm
//@ build-pass
#![feature(extended_varargs_abi_support)]
fn aapcs(f: extern "aapcs" fn(usize, ...)) {
f(22, 44);
}
fn main() {}

View file

@ -1,28 +0,0 @@
#![feature(extended_varargs_abi_support)]
fn baz(f: extern "Rust" fn(usize, ...)) {
//~^ ERROR: C-variadic functions with the "Rust" calling convention are not supported
f(22, 44);
}
#[cfg(target_arch = "x86_64")]
fn sysv(f: extern "sysv64" fn(usize, ...)) {
f(22, 44);
}
#[cfg(target_arch = "x86_64")]
fn win(f: extern "win64" fn(usize, ...)) {
f(22, 44);
}
#[cfg(any(
target_arch = "arm",
target_arch = "aarch64",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "x86",
target_arch = "x86_64"
))]
fn efiapi(f: extern "efiapi" fn(usize, ...)) {
f(22, 44);
}
fn main() {}

View file

@ -1,9 +0,0 @@
error[E0045]: C-variadic functions with the "Rust" calling convention are not supported
--> $DIR/variadic-ffi-2.rs:3:11
|
LL | fn baz(f: extern "Rust" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0045`.