Skip to content

Commit 52d37d3

Browse files
committed
c-variadic: add assembly test files
1 parent cc3a394 commit 52d37d3

6 files changed

Lines changed: 1066 additions & 0 deletions

File tree

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
//@ add-minicore
2+
//@ assembly-output: emit-asm
3+
//
4+
//@ revisions: AARCH64_LINUX AARCH64_DARWIN
5+
//@ [AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu
6+
//@ [AARCH64_LINUX] needs-llvm-components: aarch64
7+
//@ [AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin
8+
//@ [AARCH64_DARWIN] needs-llvm-components: aarch64
9+
#![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs)]
10+
#![no_core]
11+
#![crate_type = "lib"]
12+
13+
// Check that the assembly that rustc generates matches what clang emits.
14+
15+
// For aarch64-unknown-linux-gnu LLVM canonicalizes a comparison, leading to slightly different
16+
// assembly.
17+
//
18+
// For aarch64-apple-darwin LLVM is able to optimize our output better, because we effectively
19+
// desugar va_arg early, hence we don't actually match Clang there.
20+
21+
extern crate minicore;
22+
use minicore::*;
23+
24+
#[lang = "va_arg_safe"]
25+
pub unsafe trait VaArgSafe {}
26+
27+
unsafe impl VaArgSafe for i32 {}
28+
unsafe impl VaArgSafe for i64 {}
29+
unsafe impl VaArgSafe for i128 {}
30+
unsafe impl VaArgSafe for f64 {}
31+
unsafe impl<T> VaArgSafe for *const T {}
32+
33+
#[repr(transparent)]
34+
struct VaListInner {
35+
ptr: *const c_void,
36+
}
37+
38+
#[repr(transparent)]
39+
#[lang = "va_list"]
40+
pub struct VaList<'a> {
41+
inner: VaListInner,
42+
_marker: PhantomData<&'a mut ()>,
43+
}
44+
45+
#[rustc_intrinsic]
46+
#[rustc_nounwind]
47+
pub const unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaList<'_>) -> T;
48+
49+
#[unsafe(no_mangle)]
50+
unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 {
51+
// AARCH64_LINUX-LABEL: read_f64:
52+
// AARCH64_LINUX: ldrsw x8, [x0, #28]
53+
// AARCH64_LINUX-NEXT: tbz w8, #31, .LBB0_2
54+
// AARCH64_LINUX-NEXT: add w9, w8, #16
55+
// AARCH64_LINUX-NEXT: cmn w8, #16
56+
// AARCH64_LINUX-NEXT: str w9, [x0, #28]
57+
// AARCH64_LINUX-NEXT: b.ls .LBB0_3
58+
// AARCH64_LINUX-NEXT: .LBB0_2:
59+
// AARCH64_LINUX-NEXT: ldr x8, [x0]
60+
// AARCH64_LINUX-NEXT: ldr d0, [x8]
61+
// AARCH64_LINUX-NEXT: add x9, x8, #8
62+
// AARCH64_LINUX-NEXT: str x9, [x0]
63+
// AARCH64_LINUX-NEXT: ret
64+
// AARCH64_LINUX-NEXT: .LBB0_3
65+
// AARCH64_LINUX-NEXT: ldr x9, [x0, #16]
66+
// AARCH64_LINUX-NEXT: add x8, x9, x8
67+
// AARCH64_LINUX-NEXT: ldr d0, [x8]
68+
// AARCH64_LINUX-NEXT: ret
69+
//
70+
// AARCH64_DARWIN-LABEL: _read_f64:
71+
// AARCH64_DARWIN: ldr x8, [x0]
72+
// AARCH64_DARWIN-NEXT: ldr d0, [x8], #8
73+
// AARCH64_DARWIN-NEXT: str x8, [x0]
74+
// AARCH64_DARWIN-NEXT: ret
75+
va_arg(ap)
76+
}
77+
78+
#[unsafe(no_mangle)]
79+
unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 {
80+
// AARCH64_LINUX-LABEL: read_i32:
81+
// AARCH64_LINUX: ldrsw x8, [x0, #24]
82+
// AARCH64_LINUX-NEXT: tbz w8, #31, .LBB1_2
83+
// AARCH64_LINUX-NEXT: add w9, w8, #8
84+
// AARCH64_LINUX-NEXT: cmn w8, #8
85+
// AARCH64_LINUX-NEXT: str w9, [x0, #24]
86+
// AARCH64_LINUX-NEXT: b.ls .LBB1_3
87+
// AARCH64_LINUX-NEXT: .LBB1_2:
88+
// AARCH64_LINUX-NEXT: ldr x8, [x0]
89+
// AARCH64_LINUX-NEXT: add x9, x8, #8
90+
// AARCH64_LINUX-NEXT: str x9, [x0]
91+
// AARCH64_LINUX-NEXT: ldr w0, [x8]
92+
// AARCH64_LINUX-NEXT: ret
93+
// AARCH64_LINUX-NEXT: .LBB1_3
94+
// AARCH64_LINUX-NEXT: ldr x9, [x0, #8]
95+
// AARCH64_LINUX-NEXT: add x8, x9, x8
96+
// AARCH64_LINUX-NEXT: ldr w0, [x8]
97+
// AARCH64_LINUX-NEXT: ret
98+
//
99+
// AARCH64_DARWIN-LABEL: _read_i32:
100+
// AARCH64_DARWIN: ldr x9, [x0]
101+
// AARCH64_DARWIN-NEXT: ldr w8, [x9], #8
102+
// AARCH64_DARWIN-NEXT: str x9, [x0]
103+
// AARCH64_DARWIN-NEXT: mov x0, x8
104+
// AARCH64_DARWIN-NEXT: ret
105+
va_arg(ap)
106+
}
107+
108+
#[unsafe(no_mangle)]
109+
unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 {
110+
// AARCH64_LINUX-LABEL: read_i64:
111+
// AARCH64_LINUX: ldrsw x8, [x0, #24]
112+
// AARCH64_LINUX-NEXT: tbz w8, #31, .LBB2_2
113+
// AARCH64_LINUX-NEXT: add w9, w8, #8
114+
// AARCH64_LINUX-NEXT: cmn w8, #8
115+
// AARCH64_LINUX-NEXT: str w9, [x0, #24]
116+
// AARCH64_LINUX-NEXT: b.ls .LBB2_3
117+
// AARCH64_LINUX-NEXT: .LBB2_2:
118+
// AARCH64_LINUX-NEXT: ldr x8, [x0]
119+
// AARCH64_LINUX-NEXT: add x9, x8, #8
120+
// AARCH64_LINUX-NEXT: str x9, [x0]
121+
// AARCH64_LINUX-NEXT: ldr x0, [x8]
122+
// AARCH64_LINUX-NEXT: ret
123+
// AARCH64_LINUX-NEXT: .LBB2_3
124+
// AARCH64_LINUX-NEXT: ldr x9, [x0, #8]
125+
// AARCH64_LINUX-NEXT: add x8, x9, x8
126+
// AARCH64_LINUX-NEXT: ldr x0, [x8]
127+
// AARCH64_LINUX-NEXT: ret
128+
//
129+
// AARCH64_DARWIN-LABEL: _read_i64:
130+
// AARCH64_DARWIN: ldr x9, [x0]
131+
// AARCH64_DARWIN-NEXT: ldr x8, [x9], #8
132+
// AARCH64_DARWIN-NEXT: str x9, [x0]
133+
// AARCH64_DARWIN-NEXT: mov x0, x8
134+
// AARCH64_DARWIN-NEXT: ret
135+
va_arg(ap)
136+
}
137+
138+
#[unsafe(no_mangle)]
139+
unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 {
140+
// AARCH64_LINUX-LABEL: read_i128:
141+
// AARCH64_LINUX: ldrsw x8, [x0, #24]
142+
// AARCH64_LINUX-NEXT: tbz w8, #31, .LBB3_2
143+
// AARCH64_LINUX-NEXT: add x8, x8, #15
144+
// AARCH64_LINUX-NEXT: and x8, x8, #0xfffffffffffffff0
145+
// AARCH64_LINUX-NEXT: add w9, w8, #16
146+
// AARCH64_LINUX-NEXT: cmp w9, #0
147+
// AARCH64_LINUX-NEXT: str w9, [x0, #24]
148+
// AARCH64_LINUX-NEXT: b.le .LBB3_3
149+
// AARCH64_LINUX-NEXT: .LBB3_2:
150+
// AARCH64_LINUX-NEXT: ldr x8, [x0]
151+
// AARCH64_LINUX-NEXT: add x8, x8, #15
152+
// AARCH64_LINUX-NEXT: and x8, x8, #0xfffffffffffffff0
153+
// AARCH64_LINUX-NEXT: add x9, x8, #16
154+
// AARCH64_LINUX-NEXT: str x9, [x0]
155+
// AARCH64_LINUX-NEXT: ldp x0, x1, [x8]
156+
// AARCH64_LINUX-NEXT: ret
157+
// AARCH64_LINUX-NEXT: .LBB3_3
158+
// AARCH64_LINUX-NEXT: ldr x9, [x0, #8]
159+
// AARCH64_LINUX-NEXT: add x8, x9, x8
160+
// AARCH64_LINUX-NEXT: ldp x0, x1, [x8]
161+
// AARCH64_LINUX-NEXT: ret
162+
//
163+
// AARCH64_DARWIN-LABEL: _read_i128:
164+
// AARCH64_DARWIN: ldr x8, [x0]
165+
// AARCH64_DARWIN-NEXT: add x8, x8, #15
166+
// AARCH64_DARWIN-NEXT: and x9, x8, #0xfffffffffffffff0
167+
// AARCH64_DARWIN-NEXT: ldr x1, [x9, #8]
168+
// AARCH64_DARWIN-NEXT: ldr x8, [x9], #16
169+
// AARCH64_DARWIN-NEXT: str x9, [x0]
170+
// AARCH64_DARWIN-NEXT: mov x0, x8
171+
// AARCH64_DARWIN-NEXT: ret
172+
va_arg(ap)
173+
}
174+
175+
#[unsafe(no_mangle)]
176+
unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 {
177+
// AARCH64_LINUX-CHECK: read_ptr = read_i64
178+
// AARCH64_DARWIN-CHECK: _read_ptr = _read_i64
179+
va_arg(ap)
180+
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
//@ add-minicore
2+
//@ assembly-output: emit-asm
3+
//
4+
//@ revisions: POWERPC POWERPC64 POWERPC64LE AIX
5+
//@ [POWERPC] compile-flags: -Copt-level=3 --target powerpc-unknown-linux-gnu
6+
//@ [POWERPC] needs-llvm-components: powerpc
7+
//@ [POWERPC64] compile-flags: -Copt-level=3 --target powerpc64-unknown-linux-gnu
8+
//@ [POWERPC64] needs-llvm-components: powerpc
9+
//@ [POWERPC64LE] compile-flags: -Copt-level=3 --target powerpc64le-unknown-linux-gnu
10+
//@ [POWERPC64LE] needs-llvm-components: powerpc
11+
//@ [AIX] compile-flags: -Copt-level=3 --target powerpc64-ibm-aix
12+
//@ [AIX] needs-llvm-components: powerpc
13+
#![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs)]
14+
#![no_core]
15+
#![crate_type = "lib"]
16+
17+
// Check that the assembly that rustc generates matches what clang emits.
18+
19+
extern crate minicore;
20+
use minicore::*;
21+
22+
#[lang = "va_arg_safe"]
23+
pub unsafe trait VaArgSafe {}
24+
25+
unsafe impl VaArgSafe for i32 {}
26+
unsafe impl VaArgSafe for i64 {}
27+
#[cfg(target_pointer_width = "64")]
28+
unsafe impl VaArgSafe for i128 {}
29+
unsafe impl VaArgSafe for f64 {}
30+
unsafe impl<T> VaArgSafe for *const T {}
31+
32+
#[repr(transparent)]
33+
struct VaListInner {
34+
ptr: *const c_void,
35+
}
36+
37+
#[repr(transparent)]
38+
#[lang = "va_list"]
39+
pub struct VaList<'a> {
40+
inner: VaListInner,
41+
_marker: PhantomData<&'a mut ()>,
42+
}
43+
44+
#[rustc_intrinsic]
45+
#[rustc_nounwind]
46+
pub const unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaList<'_>) -> T;
47+
48+
#[unsafe(no_mangle)]
49+
unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 {
50+
// CHECK-LABEL: read_f64
51+
//
52+
// POWERPC: lbz 5, 1(3)
53+
// POWERPC-NEXT: cmplwi 5, 7
54+
// POWERPC-NEXT: bgt 0, .LBB0_2
55+
// POWERPC-NEXT: lwz 4, 8(3)
56+
// POWERPC-NEXT: rlwinm 6, 5, 3, 24, 28
57+
// POWERPC-NEXT: addi 5, 5, 1
58+
// POWERPC-NEXT: add 4, 4, 6
59+
// POWERPC-NEXT: addi 4, 4, 32
60+
// POWERPC-NEXT: lfd 1, 0(4)
61+
// POWERPC-NEXT: stb 5, 1(3)
62+
// POWERPC-NEXT: blr
63+
//
64+
// POWERPC64: ld 4, 0(3)
65+
// POWERPC64-NEXT: lfd 1, 0(4)
66+
// POWERPC64-NEXT: addi 4, 4, 8
67+
// POWERPC64-NEXT: std 4, 0(3)
68+
// POWERPC64-NEXT: blr
69+
//
70+
// POWERPC64LE: ld 4, 0(3)
71+
// POWERPC64LE-NEXT: lfd 1, 0(4)
72+
// POWERPC64LE-NEXT: addi 5, 4, 8
73+
// POWERPC64LE-NEXT: std 5, 0(3)
74+
// POWERPC64LE-NEXT: blr
75+
//
76+
// AIX: ld 4, 0(3)
77+
// AIX-NEXT: lfd 1, 0(4)
78+
// AIX-NEXT: addi 5, 4, 8
79+
// AIX-NEXT: std 5, 0(3)
80+
// AIX-NEXT: blr
81+
va_arg(ap)
82+
}
83+
84+
#[unsafe(no_mangle)]
85+
unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 {
86+
// CHECK-LABEL: read_i32
87+
//
88+
// POWERPC: lbz 5, 0(3)
89+
// POWERPC-NEXT: mr 4, 3
90+
// POWERPC-NEXT: cmplwi 5, 7
91+
// POWERPC-NEXT: bgt 0, .LBB1_2
92+
// POWERPC-NEXT: lwz 3, 8(4)
93+
// POWERPC-NEXT: rlwinm 6, 5, 2, 24, 29
94+
// POWERPC-NEXT: addi 5, 5, 1
95+
// POWERPC-NEXT: add 3, 3, 6
96+
// POWERPC-NEXT: lwz 3, 0(3)
97+
// POWERPC-NEXT: stb 5, 0(4)
98+
// POWERPC-NEXT: blr
99+
//
100+
// POWERPC64: ld 5, 0(3)
101+
// POWERPC64-NEXT: mr 4, 3
102+
// POWERPC64-NEXT: lwa 3, 4(5)
103+
// POWERPC64-NEXT: addi 5, 5, 8
104+
// POWERPC64-NEXT: std 5, 0(4)
105+
// POWERPC64-NEXT: blr
106+
//
107+
// POWERPC64LE: ld 4, 0(3)
108+
// POWERPC64LE-NEXT: addi 5, 4, 8
109+
// POWERPC64LE-NEXT: std 5, 0(3)
110+
// POWERPC64LE-NEXT: lwa 3, 0(4)
111+
// POWERPC64LE-NEXT: blr
112+
//
113+
// AIX: ld 4, 0(3)
114+
// AIX-NEXT: addi 5, 4, 8
115+
// AIX-NEXT: std 5, 0(3)
116+
// AIX-NEXT: lwa 3, 4(4)
117+
// AIX-NEXT: blr
118+
va_arg(ap)
119+
}
120+
121+
#[unsafe(no_mangle)]
122+
unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 {
123+
// CHECK-LABEL: read_i64
124+
//
125+
// POWERPC: mr 5, 3
126+
// POWERPC-NEXT: lbz 3, 0(3)
127+
// POWERPC-NEXT: addi 3, 3, 1
128+
// POWERPC-NEXT: clrlwi 4, 3, 24
129+
// POWERPC-NEXT: cmplwi 4, 7
130+
// POWERPC-NEXT: bgt 0, .LBB2_2
131+
// POWERPC-NEXT: lwz 4, 8(5)
132+
// POWERPC-NEXT: rlwinm 6, 3, 0, 29, 30
133+
// POWERPC-NEXT: rlwinm 3, 3, 2, 27, 28
134+
// POWERPC-NEXT: addi 6, 6, 2
135+
// POWERPC-NEXT: add 4, 4, 3
136+
// POWERPC-NEXT: lwz 3, 0(4)
137+
// POWERPC-NEXT: lwz 4, 4(4)
138+
// POWERPC-NEXT: stb 6, 0(5)
139+
// POWERPC-NEXT: blr
140+
//
141+
// POWERPC64: ld 5, 0(3)
142+
// POWERPC64-NEXT: mr 4, 3
143+
// POWERPC64-NEXT: ld 3, 0(5)
144+
// POWERPC64-NEXT: addi 5, 5, 8
145+
// POWERPC64-NEXT: std 5, 0(4)
146+
// POWERPC64-NEXT: blr
147+
//
148+
// POWERPC64LE: ld 4, 0(3)
149+
// POWERPC64LE-NEXT: addi 5, 4, 8
150+
// POWERPC64LE-NEXT: std 5, 0(3)
151+
// POWERPC64LE-NEXT: ld 3, 0(4)
152+
// POWERPC64LE-NEXT: blr
153+
//
154+
// AIX: ld 4, 0(3)
155+
// AIX-NEXT: addi 5, 4, 8
156+
// AIX-NEXT: std 5, 0(3)
157+
// AIX-NEXT: ld 3, 0(4)
158+
// AIX-NEXT: blr
159+
va_arg(ap)
160+
}
161+
162+
#[unsafe(no_mangle)]
163+
#[cfg(target_pointer_width = "64")]
164+
unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 {
165+
// POWERPC64-LABEL: read_i128
166+
// POWERPC64: ld 6, 0(3)
167+
// POWERPC64-NEXT: mr 5, 3
168+
// POWERPC64-NEXT: ld 3, 0(6)
169+
// POWERPC64-NEXT: ld 4, 8(6)
170+
// POWERPC64-NEXT: addi 6, 6, 16
171+
// POWERPC64-NEXT: std 6, 0(5)
172+
// POWERPC64-NEXT: blr
173+
//
174+
// POWERPC64LE-LABEL: read_i128
175+
// POWERPC64LE: ld 4, 0(3)
176+
// POWERPC64LE-NEXT: addi 5, 4, 16
177+
// POWERPC64LE-NEXT: std 5, 0(3)
178+
// POWERPC64LE-NEXT: ld 3, 0(4)
179+
// POWERPC64LE-NEXT: ld 4, 8(4)
180+
// POWERPC64LE-NEXT: blr
181+
//
182+
// AIX-LABEL: read_i128
183+
// AIX: ld 4, 0(3)
184+
// AIX-NEXT: addi 5, 4, 16
185+
// AIX-NEXT: std 5, 0(3)
186+
// AIX-NEXT: ld 3, 0(4)
187+
// AIX-NEXT: ld 4, 8(4)
188+
// AIX-NEXT: blr
189+
va_arg(ap)
190+
}
191+
192+
#[unsafe(no_mangle)]
193+
unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 {
194+
// POWERPC: read_ptr = read_i32
195+
// POWERPC64: read_ptr = read_i64
196+
// POWERPC64LE: read_ptr = read_i64
197+
va_arg(ap)
198+
}

0 commit comments

Comments
 (0)