|
| 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-msvc |
| 39 | + |
| 40 | +// note: msvc is ignored as rust_test_helpers does not have the sysv64 abi on msvc |
| 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 | +} |
0 commit comments