about summary refs log tree commit diff
path: root/tests/ui/c-variadic/same-program-multiple-abis-arm.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-21 22:57:46 +0000
committerbors <bors@rust-lang.org>2025-08-21 22:57:46 +0000
commit8e3710ef31a0b2cdf5a1c2f3929b7735d1e28c20 (patch)
treefd4b586c55cb9c9d40c84180d4ece8c70110963e /tests/ui/c-variadic/same-program-multiple-abis-arm.rs
parent6ba0ce40941eee1ca02e9ba49c791ada5158747a (diff)
parent7d2993daf3866947877e285d99235a00332a4e99 (diff)
downloadrust-8e3710ef31a0b2cdf5a1c2f3929b7735d1e28c20.tar.gz
rust-8e3710ef31a0b2cdf5a1c2f3929b7735d1e28c20.zip
Auto merge of #145728 - jhpratt:rollup-nwbw8de, r=jhpratt
Rollup of 16 pull requests

Successful merges:

 - rust-lang/rust#137494 (libstd: init(): dup() subsequent /dev/nulls instead of opening them again)
 - rust-lang/rust#144541 (c-variadic: multiple ABIs in the same program for arm)
 - rust-lang/rust#144613 (aarch64-nintendo-switch-freestanding - Enable CPU features that are always available in a live system (crypto instructions, plus explicit NEON).)
 - rust-lang/rust#144780 (Add a method to dump MIR in the middle of MIR building)
 - rust-lang/rust#145137 (Consolidate panicking functions in `slice/index.rs`)
 - rust-lang/rust#145507 (Refactor attribute parsing to improve ergonomics and some diagnostics)
 - rust-lang/rust#145604 (Gate static closures behind a parser feature)
 - rust-lang/rust#145648 (Add two tidy dependency checks)
 - rust-lang/rust#145661 (update some s390x codegen tests)
 - rust-lang/rust#145672 (Instantiate higher-ranked binder with erased when checking `IntoIterator` predicate for query instability)
 - rust-lang/rust#145689 (Migrate `panic_unwind` to use `cfg_select!`)
 - rust-lang/rust#145700 (Handle `ReEarlyParam` in `type_name`.)
 - rust-lang/rust#145703 (Remove MIPS targets from CI LLVM platforms)
 - rust-lang/rust#145704 (ci: don't cleanup windows disk)
 - rust-lang/rust#145705 (remove an `as` cast in prefetch codegen)
 - rust-lang/rust#145712 (Update outdated link in bound region comments)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'tests/ui/c-variadic/same-program-multiple-abis-arm.rs')
-rw-r--r--tests/ui/c-variadic/same-program-multiple-abis-arm.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/tests/ui/c-variadic/same-program-multiple-abis-arm.rs b/tests/ui/c-variadic/same-program-multiple-abis-arm.rs
new file mode 100644
index 00000000000..1b0bdecabfb
--- /dev/null
+++ b/tests/ui/c-variadic/same-program-multiple-abis-arm.rs
@@ -0,0 +1,77 @@
+#![feature(extended_varargs_abi_support)]
+//@ run-pass
+//@ only-arm
+//@ ignore-thumb (this test uses arm assembly)
+//@ only-eabihf (the assembly below requires float hardware support)
+
+// Check that multiple c-variadic calling conventions can be used in the same program.
+//
+// Clang and gcc reject defining functions with a non-default calling convention and a variable
+// argument list, so C programs that use multiple c-variadic calling conventions are unlikely
+// to come up. Here we validate that our codegen backends do in fact generate correct code.
+
+extern "C" {
+    fn variadic_c(_: f64, _: ...) -> f64;
+}
+
+extern "aapcs" {
+    fn variadic_aapcs(_: f64, _: ...) -> f64;
+}
+
+fn main() {
+    unsafe {
+        assert_eq!(variadic_c(1.0, 2.0, 3.0), 1.0 + 2.0 + 3.0);
+        assert_eq!(variadic_aapcs(1.0, 2.0, 3.0), 1.0 + 2.0 + 3.0);
+    }
+}
+
+// This assembly was generated using https://godbolt.org/z/xcW6a1Tj5, and corresponds to the
+// following code compiled for the `armv7-unknown-linux-gnueabihf` target:
+//
+// ```rust
+// #![feature(c_variadic)]
+//
+// #[unsafe(no_mangle)]
+// unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
+//     let b = args.arg::<f64>();
+//     let c = args.arg::<f64>();
+//
+//     a + b + c
+// }
+// ```
+//
+// This function uses floats (and passes one normal float argument) because the aapcs and C calling
+// conventions differ in how floats are passed, e.g. https://godbolt.org/z/sz799f51x. However, for
+// c-variadic functions, both ABIs actually behave the same, based on:
+//
+// https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#65parameter-passing
+//
+// > A variadic function is always marshaled as for the base standard.
+//
+// https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#7the-standard-variants
+//
+// > This section applies only to non-variadic functions. For a variadic function the base standard
+// > is always used both for argument passing and result return.
+core::arch::global_asm!(
+    r#"
+{variadic_c}:
+{variadic_aapcs}:
+        sub     sp, sp, #12
+        stmib   sp, {{r2, r3}}
+        vmov    d0, r0, r1
+        add     r0, sp, #4
+        vldr    d1, [sp, #4]
+        add     r0, r0, #15
+        bic     r0, r0, #7
+        vadd.f64        d0, d0, d1
+        add     r1, r0, #8
+        str     r1, [sp]
+        vldr    d1, [r0]
+        vadd.f64        d0, d0, d1
+        vmov    r0, r1, d0
+        add     sp, sp, #12
+        bx      lr
+    "#,
+    variadic_c = sym variadic_c,
+    variadic_aapcs = sym variadic_aapcs,
+);