Skip to content

Commit 65bd9cd

Browse files
Rollup merge of rust-lang#144379 - folkertdev:c-variadic-same-program-multiple-abis, r=RalfJung
test using multiple c-variadic ABIs in the same program tracking issue: rust-lang#100189 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. (CI will not run this test because it runs on aarch64, I would like to at least test that this runs on windows) try-job: `x86_64-gnu` try-job: `x86_64-msvc-*`
2 parents 8326fc8 + 963cd8a commit 65bd9cd

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#![feature(extended_varargs_abi_support)]
2+
//@ run-pass
3+
//@ only-x86_64
4+
5+
// Check that multiple c-variadic calling conventions can be used in the same program.
6+
//
7+
// Clang and gcc reject defining functions with a non-default calling convention and a variable
8+
// argument list, so C programs that use multiple c-variadic calling conventions are unlikely
9+
// to come up. Here we validate that our codegen backends do in fact generate correct code.
10+
11+
extern "sysv64" {
12+
fn variadic_sysv64(_: u32, _: ...) -> u32;
13+
}
14+
15+
extern "win64" {
16+
fn variadic_win64(_: u32, _: ...) -> u32;
17+
}
18+
19+
fn main() {
20+
unsafe {
21+
assert_eq!(variadic_win64(1, 2, 3), 1 + 2 + 3);
22+
assert_eq!(variadic_sysv64(1, 2, 3), 1 + 2 + 3);
23+
}
24+
}
25+
26+
// This assembly was generated using https://godbolt.org/z/dbTGanoh6, and corresponds to the
27+
// following code compiled for the `x86_64-unknown-linux-gnu` and `x86_64-pc-windows-gnu`
28+
// targets, respectively:
29+
//
30+
// ```rust
31+
// #![feature(c_variadic)]
32+
//
33+
// #[unsafe(no_mangle)]
34+
// unsafe extern "C" fn variadic(a: u32, mut args: ...) -> u32 {
35+
// let b = args.arg::<u32>();
36+
// let c = args.arg::<u32>();
37+
//
38+
// a + b + c
39+
// }
40+
// ```
41+
core::arch::global_asm!(
42+
r#"
43+
variadic_sysv64:
44+
sub rsp, 88
45+
test al, al
46+
je .LBB0_7
47+
movaps xmmword ptr [rsp - 48], xmm0
48+
movaps xmmword ptr [rsp - 32], xmm1
49+
movaps xmmword ptr [rsp - 16], xmm2
50+
movaps xmmword ptr [rsp], xmm3
51+
movaps xmmword ptr [rsp + 16], xmm4
52+
movaps xmmword ptr [rsp + 32], xmm5
53+
movaps xmmword ptr [rsp + 48], xmm6
54+
movaps xmmword ptr [rsp + 64], xmm7
55+
.LBB0_7:
56+
mov qword ptr [rsp - 88], rsi
57+
mov qword ptr [rsp - 80], rdx
58+
mov qword ptr [rsp - 72], rcx
59+
mov qword ptr [rsp - 64], r8
60+
mov qword ptr [rsp - 56], r9
61+
movabs rax, 206158430216
62+
mov qword ptr [rsp - 120], rax
63+
lea rax, [rsp + 96]
64+
mov qword ptr [rsp - 112], rax
65+
lea rax, [rsp - 96]
66+
mov qword ptr [rsp - 104], rax
67+
mov edx, 8
68+
cmp rdx, 41
69+
jae .LBB0_1
70+
mov rax, qword ptr [rsp - 104]
71+
mov ecx, 8
72+
add rcx, 8
73+
mov dword ptr [rsp - 120], ecx
74+
mov eax, dword ptr [rax + rdx]
75+
cmp edx, 32
76+
ja .LBB0_2
77+
add rcx, qword ptr [rsp - 104]
78+
add edx, 16
79+
mov dword ptr [rsp - 120], edx
80+
add eax, edi
81+
add eax, dword ptr [rcx]
82+
add rsp, 88
83+
ret
84+
.LBB0_1:
85+
mov rax, qword ptr [rsp - 112]
86+
lea rcx, [rax + 8]
87+
mov qword ptr [rsp - 112], rcx
88+
mov eax, dword ptr [rax]
89+
.LBB0_2:
90+
mov rcx, qword ptr [rsp - 112]
91+
lea rdx, [rcx + 8]
92+
mov qword ptr [rsp - 112], rdx
93+
add eax, edi
94+
add eax, dword ptr [rcx]
95+
add rsp, 88
96+
ret
97+
98+
variadic_win64:
99+
push rax
100+
mov qword ptr [rsp + 40], r9
101+
mov qword ptr [rsp + 24], rdx
102+
mov qword ptr [rsp + 32], r8
103+
lea rax, [rsp + 40]
104+
mov qword ptr [rsp], rax
105+
lea eax, [rdx + rcx]
106+
add eax, r8d
107+
pop rcx
108+
ret
109+
"#
110+
);

0 commit comments

Comments
 (0)