]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/abi-sysv64-arg-passing.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / test / run-pass / abi-sysv64-arg-passing.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Checks if the "sysv64" calling convention behaves the same as the
12 // "C" calling convention on platforms where both should be the same
13
14 // This file contains versions of the following run-pass tests with
15 // the calling convention changed to "sysv64"
16
17 // cabi-int-widening
18 // extern-pass-char
19 // extern-pass-u32
20 // extern-pass-u64
21 // extern-pass-double
22 // extern-pass-empty
23 // extern-pass-TwoU8s
24 // extern-pass-TwoU16s
25 // extern-pass-TwoU32s
26 // extern-pass-TwoU64s
27 // extern-return-TwoU8s
28 // extern-return-TwoU16s
29 // extern-return-TwoU32s
30 // extern-return-TwoU64s
31 // foreign-fn-with-byval
32 // issue-28676
33 // struct-return
34
35 // ignore-android
36 // ignore-arm
37 // ignore-aarch64
38 // ignore-windows
39
40 // note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows
41
42 #![feature(abi_sysv64)]
43 #[allow(dead_code)]
44 #[allow(improper_ctypes)]
45
46 #[cfg(target_arch = "x86_64")]
47 mod tests {
48     #[repr(C)]
49     #[derive(Copy, Clone, PartialEq, Debug)]
50     pub struct TwoU8s {
51         one: u8, two: u8
52     }
53
54     #[repr(C)]
55     #[derive(Copy, Clone, PartialEq, Debug)]
56     pub struct TwoU16s {
57         one: u16, two: u16
58     }
59
60     #[repr(C)]
61     #[derive(Copy, Clone, PartialEq, Debug)]
62     pub struct TwoU32s {
63         one: u32, two: u32
64     }
65
66     #[repr(C)]
67     #[derive(Copy, Clone, PartialEq, Debug)]
68     pub struct TwoU64s {
69         one: u64, two: u64
70     }
71
72     #[repr(C)]
73     pub struct ManyInts {
74         arg1: i8,
75         arg2: i16,
76         arg3: i32,
77         arg4: i16,
78         arg5: i8,
79         arg6: TwoU8s,
80     }
81
82     #[repr(C)]
83     pub struct Empty;
84
85     #[repr(C)]
86     #[derive(Copy, Clone)]
87     pub struct S {
88         x: u64,
89         y: u64,
90         z: u64,
91     }
92
93     #[repr(C)]
94     #[derive(Copy, Clone)]
95     pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
96
97     #[repr(C)]
98     #[derive(Copy, Clone)]
99     pub struct Floats { a: f64, b: u8, c: f64 }
100
101     #[link(name = "rust_test_helpers")]
102     extern "sysv64" {
103         pub fn rust_int8_to_int32(_: i8) -> i32;
104         pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
105         pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
106         pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
107         pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
108         pub fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
109         pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s;
110         pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s;
111         pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
112         pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
113         pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
114         pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
115         pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
116         pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
117         pub fn get_x(x: S) -> u64;
118         pub fn get_y(x: S) -> u64;
119         pub fn get_z(x: S) -> u64;
120         pub fn get_c_many_params(_: *const (), _: *const (),
121                                  _: *const (), _: *const (), f: Quad) -> u64;
122         pub fn rust_dbg_abi_1(q: Quad) -> Quad;
123         pub fn rust_dbg_abi_2(f: Floats) -> Floats;
124     }
125
126     pub fn cabi_int_widening() {
127         let x = unsafe {
128             rust_int8_to_int32(-1)
129         };
130
131         assert!(x == -1);
132     }
133
134     pub fn extern_pass_char() {
135         unsafe {
136             assert_eq!(22, rust_dbg_extern_identity_u8(22));
137         }
138     }
139
140     pub fn extern_pass_u32() {
141         unsafe {
142             assert_eq!(22, rust_dbg_extern_identity_u32(22));
143         }
144     }
145
146     pub fn extern_pass_u64() {
147         unsafe {
148             assert_eq!(22, rust_dbg_extern_identity_u64(22));
149         }
150     }
151
152     pub fn extern_pass_double() {
153         unsafe {
154             assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64));
155         }
156     }
157
158     pub fn extern_pass_empty() {
159         unsafe {
160             let x = ManyInts {
161                 arg1: 2,
162                 arg2: 3,
163                 arg3: 4,
164                 arg4: 5,
165                 arg5: 6,
166                 arg6: TwoU8s { one: 7, two: 8, }
167             };
168             let y = ManyInts {
169                 arg1: 1,
170                 arg2: 2,
171                 arg3: 3,
172                 arg4: 4,
173                 arg5: 5,
174                 arg6: TwoU8s { one: 6, two: 7, }
175             };
176             let empty = Empty;
177             rust_dbg_extern_empty_struct(x, empty, y);
178         }
179     }
180
181     pub fn extern_pass_twou8s() {
182         unsafe {
183             let x = TwoU8s {one: 22, two: 23};
184             let y = rust_dbg_extern_identity_TwoU8s(x);
185             assert_eq!(x, y);
186         }
187     }
188
189     pub fn extern_pass_twou16s() {
190         unsafe {
191             let x = TwoU16s {one: 22, two: 23};
192             let y = rust_dbg_extern_identity_TwoU16s(x);
193             assert_eq!(x, y);
194         }
195     }
196
197     pub fn extern_pass_twou32s() {
198         unsafe {
199             let x = TwoU32s {one: 22, two: 23};
200             let y = rust_dbg_extern_identity_TwoU32s(x);
201             assert_eq!(x, y);
202         }
203     }
204
205     pub fn extern_pass_twou64s() {
206         unsafe {
207             let x = TwoU64s {one: 22, two: 23};
208             let y = rust_dbg_extern_identity_TwoU64s(x);
209             assert_eq!(x, y);
210         }
211     }
212
213     pub fn extern_return_twou8s() {
214         unsafe {
215             let y = rust_dbg_extern_return_TwoU8s();
216             assert_eq!(y.one, 10);
217             assert_eq!(y.two, 20);
218         }
219     }
220
221     pub fn extern_return_twou16s() {
222         unsafe {
223             let y = rust_dbg_extern_return_TwoU16s();
224             assert_eq!(y.one, 10);
225             assert_eq!(y.two, 20);
226         }
227     }
228
229     pub fn extern_return_twou32s() {
230         unsafe {
231             let y = rust_dbg_extern_return_TwoU32s();
232             assert_eq!(y.one, 10);
233             assert_eq!(y.two, 20);
234         }
235     }
236
237     pub fn extern_return_twou64s() {
238         unsafe {
239             let y = rust_dbg_extern_return_TwoU64s();
240             assert_eq!(y.one, 10);
241             assert_eq!(y.two, 20);
242         }
243     }
244
245     #[inline(never)]
246     fn indirect_call(func: unsafe extern "sysv64" fn(s: S) -> u64, s: S) -> u64 {
247         unsafe {
248             func(s)
249         }
250     }
251
252     pub fn foreign_fn_with_byval() {
253         let s = S { x: 1, y: 2, z: 3 };
254         assert_eq!(s.x, indirect_call(get_x, s));
255         assert_eq!(s.y, indirect_call(get_y, s));
256         assert_eq!(s.z, indirect_call(get_z, s));
257     }
258
259     fn test() {
260         use std::ptr;
261         unsafe {
262             let null = ptr::null();
263             let q = Quad {
264                 a: 1,
265                 b: 2,
266                 c: 3,
267                 d: 4
268             };
269             assert_eq!(get_c_many_params(null, null, null, null, q), q.c);
270         }
271     }
272
273     pub fn issue_28676() {
274         test();
275     }
276
277     fn test1() {
278         unsafe {
279             let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa,
280                      b: 0xbbbb_bbbb_bbbb_bbbb,
281                      c: 0xcccc_cccc_cccc_cccc,
282                      d: 0xdddd_dddd_dddd_dddd };
283             let qq = rust_dbg_abi_1(q);
284             println!("a: {:x}", qq.a as usize);
285             println!("b: {:x}", qq.b as usize);
286             println!("c: {:x}", qq.c as usize);
287             println!("d: {:x}", qq.d as usize);
288             assert_eq!(qq.a, q.c + 1);
289             assert_eq!(qq.b, q.d - 1);
290             assert_eq!(qq.c, q.a + 1);
291             assert_eq!(qq.d, q.b - 1);
292         }
293     }
294
295     fn test2() {
296         unsafe {
297             let f = Floats { a: 1.234567890e-15_f64,
298                      b: 0b_1010_1010,
299                      c: 1.0987654321e-15_f64 };
300             let ff = rust_dbg_abi_2(f);
301             println!("a: {}", ff.a as f64);
302             println!("b: {}", ff.b as usize);
303             println!("c: {}", ff.c as f64);
304             assert_eq!(ff.a, f.c + 1.0f64);
305             assert_eq!(ff.b, 0xff);
306             assert_eq!(ff.c, f.a - 1.0f64);
307         }
308     }
309
310     pub fn struct_return() {
311         test1();
312         test2();
313     }
314 }
315
316 #[cfg(target_arch = "x86_64")]
317 fn main() {
318     use tests::*;
319     cabi_int_widening();
320     extern_pass_char();
321     extern_pass_u32();
322     extern_pass_u64();
323     extern_pass_double();
324     extern_pass_empty();
325     extern_pass_twou8s();
326     extern_pass_twou16s();
327     extern_pass_twou32s();
328     extern_pass_twou64s();
329     extern_return_twou8s();
330     extern_return_twou16s();
331     extern_return_twou32s();
332     extern_return_twou64s();
333     foreign_fn_with_byval();
334     issue_28676();
335     struct_return();
336 }
337
338 #[cfg(not(target_arch = "x86_64"))]
339 fn main() {
340
341 }