]> git.lizzy.rs Git - rust.git/blob - src/test/ui/abi/abi-sysv64-arg-passing.rs
Rollup merge of #95353 - jyn514:invalid-filter-hard-error, r=Mark-Simulacrum
[rust.git] / src / test / ui / abi / abi-sysv64-arg-passing.rs
1 // run-pass
2 // Checks if the "sysv64" calling convention behaves the same as the
3 // "C" calling convention on platforms where both should be the same
4
5 // This file contains versions of the following run-pass tests with
6 // the calling convention changed to "sysv64"
7
8 // cabi-int-widening
9 // extern-pass-char
10 // extern-pass-u32
11 // extern-pass-u64
12 // extern-pass-double
13 // extern-pass-empty
14 // extern-pass-TwoU8s
15 // extern-pass-TwoU16s
16 // extern-pass-TwoU32s
17 // extern-pass-TwoU64s
18 // extern-return-TwoU8s
19 // extern-return-TwoU16s
20 // extern-return-TwoU32s
21 // extern-return-TwoU64s
22 // foreign-fn-with-byval
23 // issue-28676
24 // issue-62350-sysv-neg-reg-counts
25 // struct-return
26
27 // ignore-android
28 // ignore-arm
29 // ignore-aarch64
30 // ignore-windows
31
32 // note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows
33
34 #[allow(dead_code)]
35 #[allow(improper_ctypes)]
36
37 #[cfg(target_arch = "x86_64")]
38 mod tests {
39     #[repr(C)]
40     #[derive(Copy, Clone, PartialEq, Debug)]
41     pub struct TwoU8s {
42         one: u8, two: u8
43     }
44
45     #[repr(C)]
46     #[derive(Copy, Clone, PartialEq, Debug)]
47     pub struct TwoU16s {
48         one: u16, two: u16
49     }
50
51     #[repr(C)]
52     #[derive(Copy, Clone, PartialEq, Debug)]
53     pub struct TwoU32s {
54         one: u32, two: u32
55     }
56
57     #[repr(C)]
58     #[derive(Copy, Clone, PartialEq, Debug)]
59     pub struct TwoU64s {
60         one: u64, two: u64
61     }
62
63     #[repr(C)]
64     pub struct ManyInts {
65         arg1: i8,
66         arg2: i16,
67         arg3: i32,
68         arg4: i16,
69         arg5: i8,
70         arg6: TwoU8s,
71     }
72
73     #[repr(C)]
74     pub struct Empty;
75
76     #[repr(C)]
77     #[derive(Copy, Clone)]
78     pub struct S {
79         x: u64,
80         y: u64,
81         z: u64,
82     }
83
84     #[repr(C)]
85     #[derive(Copy, Clone)]
86     pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
87
88     #[derive(Copy, Clone)]
89     pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 }
90
91     #[repr(C)]
92     #[derive(Copy, Clone)]
93     pub struct Floats { a: f64, b: u8, c: f64 }
94
95     #[repr(C, u8)]
96     pub enum U8TaggedEnumOptionU64U64 {
97         None,
98         Some(u64,u64),
99     }
100
101     #[repr(C, u8)]
102     pub enum U8TaggedEnumOptionU64 {
103         None,
104         Some(u64),
105     }
106
107     #[link(name = "rust_test_helpers", kind = "static")]
108     extern "sysv64" {
109         pub fn rust_int8_to_int32(_: i8) -> i32;
110         pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
111         pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
112         pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
113         pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
114         pub fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
115         pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s;
116         pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s;
117         pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
118         pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
119         pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
120         pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
121         pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
122         pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
123         pub fn get_x(x: S) -> u64;
124         pub fn get_y(x: S) -> u64;
125         pub fn get_z(x: S) -> u64;
126         pub fn get_c_many_params(_: *const (), _: *const (),
127                                  _: *const (), _: *const (), f: Quad) -> u64;
128         pub fn get_c_exhaust_sysv64_ints(
129             _: *const (),
130             _: *const (),
131             _: *const (),
132             _: *const (),
133             _: *const (),
134             _: *const (),
135             _: *const (),
136             h: QuadFloats,
137         ) -> f32;
138         pub fn rust_dbg_abi_1(q: Quad) -> Quad;
139         pub fn rust_dbg_abi_2(f: Floats) -> Floats;
140         pub fn rust_dbg_new_some_u64u64(a: u64, b: u64) -> U8TaggedEnumOptionU64U64;
141         pub fn rust_dbg_new_none_u64u64() -> U8TaggedEnumOptionU64U64;
142         pub fn rust_dbg_unpack_option_u64u64(
143             o: U8TaggedEnumOptionU64U64,
144             a: *mut u64,
145             b: *mut u64,
146         ) -> i32;
147         pub fn rust_dbg_new_some_u64(some: u64) -> U8TaggedEnumOptionU64;
148         pub fn rust_dbg_new_none_u64() -> U8TaggedEnumOptionU64;
149         pub fn rust_dbg_unpack_option_u64(o: U8TaggedEnumOptionU64, v: *mut u64) -> i32;
150     }
151
152     pub fn cabi_int_widening() {
153         let x = unsafe {
154             rust_int8_to_int32(-1)
155         };
156
157         assert!(x == -1);
158     }
159
160     pub fn extern_pass_char() {
161         unsafe {
162             assert_eq!(22, rust_dbg_extern_identity_u8(22));
163         }
164     }
165
166     pub fn extern_pass_u32() {
167         unsafe {
168             assert_eq!(22, rust_dbg_extern_identity_u32(22));
169         }
170     }
171
172     pub fn extern_pass_u64() {
173         unsafe {
174             assert_eq!(22, rust_dbg_extern_identity_u64(22));
175         }
176     }
177
178     pub fn extern_pass_double() {
179         unsafe {
180             assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64));
181         }
182     }
183
184     pub fn extern_pass_empty() {
185         unsafe {
186             let x = ManyInts {
187                 arg1: 2,
188                 arg2: 3,
189                 arg3: 4,
190                 arg4: 5,
191                 arg5: 6,
192                 arg6: TwoU8s { one: 7, two: 8, }
193             };
194             let y = ManyInts {
195                 arg1: 1,
196                 arg2: 2,
197                 arg3: 3,
198                 arg4: 4,
199                 arg5: 5,
200                 arg6: TwoU8s { one: 6, two: 7, }
201             };
202             let empty = Empty;
203             rust_dbg_extern_empty_struct(x, empty, y);
204         }
205     }
206
207     pub fn extern_pass_twou8s() {
208         unsafe {
209             let x = TwoU8s {one: 22, two: 23};
210             let y = rust_dbg_extern_identity_TwoU8s(x);
211             assert_eq!(x, y);
212         }
213     }
214
215     pub fn extern_pass_twou16s() {
216         unsafe {
217             let x = TwoU16s {one: 22, two: 23};
218             let y = rust_dbg_extern_identity_TwoU16s(x);
219             assert_eq!(x, y);
220         }
221     }
222
223     pub fn extern_pass_twou32s() {
224         unsafe {
225             let x = TwoU32s {one: 22, two: 23};
226             let y = rust_dbg_extern_identity_TwoU32s(x);
227             assert_eq!(x, y);
228         }
229     }
230
231     pub fn extern_pass_twou64s() {
232         unsafe {
233             let x = TwoU64s {one: 22, two: 23};
234             let y = rust_dbg_extern_identity_TwoU64s(x);
235             assert_eq!(x, y);
236         }
237     }
238
239     pub fn extern_return_twou8s() {
240         unsafe {
241             let y = rust_dbg_extern_return_TwoU8s();
242             assert_eq!(y.one, 10);
243             assert_eq!(y.two, 20);
244         }
245     }
246
247     pub fn extern_return_twou16s() {
248         unsafe {
249             let y = rust_dbg_extern_return_TwoU16s();
250             assert_eq!(y.one, 10);
251             assert_eq!(y.two, 20);
252         }
253     }
254
255     pub fn extern_return_twou32s() {
256         unsafe {
257             let y = rust_dbg_extern_return_TwoU32s();
258             assert_eq!(y.one, 10);
259             assert_eq!(y.two, 20);
260         }
261     }
262
263     pub fn extern_return_twou64s() {
264         unsafe {
265             let y = rust_dbg_extern_return_TwoU64s();
266             assert_eq!(y.one, 10);
267             assert_eq!(y.two, 20);
268         }
269     }
270
271     #[inline(never)]
272     fn indirect_call(func: unsafe extern "sysv64" fn(s: S) -> u64, s: S) -> u64 {
273         unsafe {
274             func(s)
275         }
276     }
277
278     pub fn foreign_fn_with_byval() {
279         let s = S { x: 1, y: 2, z: 3 };
280         assert_eq!(s.x, indirect_call(get_x, s));
281         assert_eq!(s.y, indirect_call(get_y, s));
282         assert_eq!(s.z, indirect_call(get_z, s));
283     }
284
285     fn test() {
286         use std::ptr;
287         unsafe {
288             let null = ptr::null();
289             let q = Quad {
290                 a: 1,
291                 b: 2,
292                 c: 3,
293                 d: 4
294             };
295             assert_eq!(get_c_many_params(null, null, null, null, q), q.c);
296         }
297     }
298
299     pub fn issue_28676() {
300         test();
301     }
302
303     fn test_62350() {
304         use std::ptr;
305         unsafe {
306             let null = ptr::null();
307             let q = QuadFloats {
308                 a: 10.2,
309                 b: 20.3,
310                 c: 30.4,
311                 d: 40.5
312             };
313             assert_eq!(
314                 get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q),
315                 q.c,
316             );
317         }
318     }
319
320     pub fn issue_62350() {
321         test_62350();
322     }
323
324     fn test1() {
325         unsafe {
326             let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa,
327                      b: 0xbbbb_bbbb_bbbb_bbbb,
328                      c: 0xcccc_cccc_cccc_cccc,
329                      d: 0xdddd_dddd_dddd_dddd };
330             let qq = rust_dbg_abi_1(q);
331             println!("a: {:x}", qq.a as usize);
332             println!("b: {:x}", qq.b as usize);
333             println!("c: {:x}", qq.c as usize);
334             println!("d: {:x}", qq.d as usize);
335             assert_eq!(qq.a, q.c + 1);
336             assert_eq!(qq.b, q.d - 1);
337             assert_eq!(qq.c, q.a + 1);
338             assert_eq!(qq.d, q.b - 1);
339         }
340     }
341
342     fn test2() {
343         unsafe {
344             let f = Floats { a: 1.234567890e-15_f64,
345                      b: 0b_1010_1010,
346                      c: 1.0987654321e-15_f64 };
347             let ff = rust_dbg_abi_2(f);
348             println!("a: {}", ff.a as f64);
349             println!("b: {}", ff.b as usize);
350             println!("c: {}", ff.c as f64);
351             assert_eq!(ff.a, f.c + 1.0f64);
352             assert_eq!(ff.b, 0xff);
353             assert_eq!(ff.c, f.a - 1.0f64);
354         }
355     }
356
357     pub fn struct_return() {
358         test1();
359         test2();
360     }
361
362     pub fn enum_passing_and_return_pair() {
363         let some_u64u64 = unsafe { rust_dbg_new_some_u64u64(10, 20) };
364         if let U8TaggedEnumOptionU64U64::Some(a, b) = some_u64u64 {
365             assert_eq!(10, a);
366             assert_eq!(20, b);
367         } else {
368             panic!("unexpected none");
369         }
370
371         let none_u64u64 = unsafe { rust_dbg_new_none_u64u64() };
372         if let U8TaggedEnumOptionU64U64::Some(_,_) = none_u64u64 {
373             panic!("unexpected some");
374         }
375
376         let mut a: u64 = 0;
377         let mut b: u64 = 0;
378         let r = unsafe {
379             rust_dbg_unpack_option_u64u64(some_u64u64, &mut a as *mut _, &mut b as *mut _)
380         };
381         assert_eq!(1, r);
382         assert_eq!(10, a);
383         assert_eq!(20, b);
384
385         let mut a: u64 = 0;
386         let mut b: u64 = 0;
387         let r = unsafe {
388             rust_dbg_unpack_option_u64u64(none_u64u64, &mut a as *mut _, &mut b as *mut _)
389         };
390         assert_eq!(0, r);
391         assert_eq!(0, a);
392         assert_eq!(0, b);
393     }
394
395     pub fn enum_passing_and_return() {
396         let some_u64 = unsafe { rust_dbg_new_some_u64(10) };
397         if let U8TaggedEnumOptionU64::Some(v) = some_u64 {
398             assert_eq!(10, v);
399         } else {
400             panic!("unexpected none");
401         }
402
403         let none_u64 = unsafe { rust_dbg_new_none_u64() };
404         if let U8TaggedEnumOptionU64::Some(_) = none_u64 {
405             panic!("unexpected some");
406         }
407
408         let mut target: u64 = 0;
409         let r = unsafe { rust_dbg_unpack_option_u64(some_u64, &mut target as *mut _) };
410         assert_eq!(1, r);
411         assert_eq!(10, target);
412
413         let mut target: u64 = 0;
414         let r = unsafe { rust_dbg_unpack_option_u64(none_u64, &mut target as *mut _) };
415         assert_eq!(0, r);
416         assert_eq!(0, target);
417     }
418 }
419
420 #[cfg(target_arch = "x86_64")]
421 fn main() {
422     use tests::*;
423     cabi_int_widening();
424     extern_pass_char();
425     extern_pass_u32();
426     extern_pass_u64();
427     extern_pass_double();
428     extern_pass_empty();
429     extern_pass_twou8s();
430     extern_pass_twou16s();
431     extern_pass_twou32s();
432     extern_pass_twou64s();
433     extern_return_twou8s();
434     extern_return_twou16s();
435     extern_return_twou32s();
436     extern_return_twou64s();
437     foreign_fn_with_byval();
438     issue_28676();
439     issue_62350();
440     struct_return();
441     enum_passing_and_return_pair();
442     enum_passing_and_return();
443 }
444
445 #[cfg(not(target_arch = "x86_64"))]
446 fn main() {
447
448 }