summaryrefslogtreecommitdiffstats
path: root/src/test/ui/abi/abi-sysv64-arg-passing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/abi/abi-sysv64-arg-passing.rs')
-rw-r--r--src/test/ui/abi/abi-sysv64-arg-passing.rs448
1 files changed, 448 insertions, 0 deletions
diff --git a/src/test/ui/abi/abi-sysv64-arg-passing.rs b/src/test/ui/abi/abi-sysv64-arg-passing.rs
new file mode 100644
index 000000000..c87353b93
--- /dev/null
+++ b/src/test/ui/abi/abi-sysv64-arg-passing.rs
@@ -0,0 +1,448 @@
+// run-pass
+// Checks if the "sysv64" calling convention behaves the same as the
+// "C" calling convention on platforms where both should be the same
+
+// This file contains versions of the following run-pass tests with
+// the calling convention changed to "sysv64"
+
+// cabi-int-widening
+// extern-pass-char
+// extern-pass-u32
+// extern-pass-u64
+// extern-pass-double
+// extern-pass-empty
+// extern-pass-TwoU8s
+// extern-pass-TwoU16s
+// extern-pass-TwoU32s
+// extern-pass-TwoU64s
+// extern-return-TwoU8s
+// extern-return-TwoU16s
+// extern-return-TwoU32s
+// extern-return-TwoU64s
+// foreign-fn-with-byval
+// issue-28676
+// issue-62350-sysv-neg-reg-counts
+// struct-return
+
+// ignore-android
+// ignore-arm
+// ignore-aarch64
+// ignore-windows
+
+// note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows
+
+#[allow(dead_code)]
+#[allow(improper_ctypes)]
+
+#[cfg(target_arch = "x86_64")]
+mod tests {
+ #[repr(C)]
+ #[derive(Copy, Clone, PartialEq, Debug)]
+ pub struct TwoU8s {
+ one: u8, two: u8
+ }
+
+ #[repr(C)]
+ #[derive(Copy, Clone, PartialEq, Debug)]
+ pub struct TwoU16s {
+ one: u16, two: u16
+ }
+
+ #[repr(C)]
+ #[derive(Copy, Clone, PartialEq, Debug)]
+ pub struct TwoU32s {
+ one: u32, two: u32
+ }
+
+ #[repr(C)]
+ #[derive(Copy, Clone, PartialEq, Debug)]
+ pub struct TwoU64s {
+ one: u64, two: u64
+ }
+
+ #[repr(C)]
+ pub struct ManyInts {
+ arg1: i8,
+ arg2: i16,
+ arg3: i32,
+ arg4: i16,
+ arg5: i8,
+ arg6: TwoU8s,
+ }
+
+ #[repr(C)]
+ pub struct Empty;
+
+ #[repr(C)]
+ #[derive(Copy, Clone)]
+ pub struct S {
+ x: u64,
+ y: u64,
+ z: u64,
+ }
+
+ #[repr(C)]
+ #[derive(Copy, Clone)]
+ pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
+
+ #[derive(Copy, Clone)]
+ pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 }
+
+ #[repr(C)]
+ #[derive(Copy, Clone)]
+ pub struct Floats { a: f64, b: u8, c: f64 }
+
+ #[repr(C, u8)]
+ pub enum U8TaggedEnumOptionU64U64 {
+ None,
+ Some(u64,u64),
+ }
+
+ #[repr(C, u8)]
+ pub enum U8TaggedEnumOptionU64 {
+ None,
+ Some(u64),
+ }
+
+ #[link(name = "rust_test_helpers", kind = "static")]
+ extern "sysv64" {
+ pub fn rust_int8_to_int32(_: i8) -> i32;
+ pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
+ pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
+ pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
+ pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
+ pub fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
+ pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s;
+ pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s;
+ pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
+ pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
+ pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
+ pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
+ pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
+ pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
+ pub fn get_x(x: S) -> u64;
+ pub fn get_y(x: S) -> u64;
+ pub fn get_z(x: S) -> u64;
+ pub fn get_c_many_params(_: *const (), _: *const (),
+ _: *const (), _: *const (), f: Quad) -> u64;
+ pub fn get_c_exhaust_sysv64_ints(
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ h: QuadFloats,
+ ) -> f32;
+ pub fn rust_dbg_abi_1(q: Quad) -> Quad;
+ pub fn rust_dbg_abi_2(f: Floats) -> Floats;
+ pub fn rust_dbg_new_some_u64u64(a: u64, b: u64) -> U8TaggedEnumOptionU64U64;
+ pub fn rust_dbg_new_none_u64u64() -> U8TaggedEnumOptionU64U64;
+ pub fn rust_dbg_unpack_option_u64u64(
+ o: U8TaggedEnumOptionU64U64,
+ a: *mut u64,
+ b: *mut u64,
+ ) -> i32;
+ pub fn rust_dbg_new_some_u64(some: u64) -> U8TaggedEnumOptionU64;
+ pub fn rust_dbg_new_none_u64() -> U8TaggedEnumOptionU64;
+ pub fn rust_dbg_unpack_option_u64(o: U8TaggedEnumOptionU64, v: *mut u64) -> i32;
+ }
+
+ pub fn cabi_int_widening() {
+ let x = unsafe {
+ rust_int8_to_int32(-1)
+ };
+
+ assert!(x == -1);
+ }
+
+ pub fn extern_pass_char() {
+ unsafe {
+ assert_eq!(22, rust_dbg_extern_identity_u8(22));
+ }
+ }
+
+ pub fn extern_pass_u32() {
+ unsafe {
+ assert_eq!(22, rust_dbg_extern_identity_u32(22));
+ }
+ }
+
+ pub fn extern_pass_u64() {
+ unsafe {
+ assert_eq!(22, rust_dbg_extern_identity_u64(22));
+ }
+ }
+
+ pub fn extern_pass_double() {
+ unsafe {
+ assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64));
+ }
+ }
+
+ pub fn extern_pass_empty() {
+ unsafe {
+ let x = ManyInts {
+ arg1: 2,
+ arg2: 3,
+ arg3: 4,
+ arg4: 5,
+ arg5: 6,
+ arg6: TwoU8s { one: 7, two: 8, }
+ };
+ let y = ManyInts {
+ arg1: 1,
+ arg2: 2,
+ arg3: 3,
+ arg4: 4,
+ arg5: 5,
+ arg6: TwoU8s { one: 6, two: 7, }
+ };
+ let empty = Empty;
+ rust_dbg_extern_empty_struct(x, empty, y);
+ }
+ }
+
+ pub fn extern_pass_twou8s() {
+ unsafe {
+ let x = TwoU8s {one: 22, two: 23};
+ let y = rust_dbg_extern_identity_TwoU8s(x);
+ assert_eq!(x, y);
+ }
+ }
+
+ pub fn extern_pass_twou16s() {
+ unsafe {
+ let x = TwoU16s {one: 22, two: 23};
+ let y = rust_dbg_extern_identity_TwoU16s(x);
+ assert_eq!(x, y);
+ }
+ }
+
+ pub fn extern_pass_twou32s() {
+ unsafe {
+ let x = TwoU32s {one: 22, two: 23};
+ let y = rust_dbg_extern_identity_TwoU32s(x);
+ assert_eq!(x, y);
+ }
+ }
+
+ pub fn extern_pass_twou64s() {
+ unsafe {
+ let x = TwoU64s {one: 22, two: 23};
+ let y = rust_dbg_extern_identity_TwoU64s(x);
+ assert_eq!(x, y);
+ }
+ }
+
+ pub fn extern_return_twou8s() {
+ unsafe {
+ let y = rust_dbg_extern_return_TwoU8s();
+ assert_eq!(y.one, 10);
+ assert_eq!(y.two, 20);
+ }
+ }
+
+ pub fn extern_return_twou16s() {
+ unsafe {
+ let y = rust_dbg_extern_return_TwoU16s();
+ assert_eq!(y.one, 10);
+ assert_eq!(y.two, 20);
+ }
+ }
+
+ pub fn extern_return_twou32s() {
+ unsafe {
+ let y = rust_dbg_extern_return_TwoU32s();
+ assert_eq!(y.one, 10);
+ assert_eq!(y.two, 20);
+ }
+ }
+
+ pub fn extern_return_twou64s() {
+ unsafe {
+ let y = rust_dbg_extern_return_TwoU64s();
+ assert_eq!(y.one, 10);
+ assert_eq!(y.two, 20);
+ }
+ }
+
+ #[inline(never)]
+ fn indirect_call(func: unsafe extern "sysv64" fn(s: S) -> u64, s: S) -> u64 {
+ unsafe {
+ func(s)
+ }
+ }
+
+ pub fn foreign_fn_with_byval() {
+ let s = S { x: 1, y: 2, z: 3 };
+ assert_eq!(s.x, indirect_call(get_x, s));
+ assert_eq!(s.y, indirect_call(get_y, s));
+ assert_eq!(s.z, indirect_call(get_z, s));
+ }
+
+ fn test() {
+ use std::ptr;
+ unsafe {
+ let null = ptr::null();
+ let q = Quad {
+ a: 1,
+ b: 2,
+ c: 3,
+ d: 4
+ };
+ assert_eq!(get_c_many_params(null, null, null, null, q), q.c);
+ }
+ }
+
+ pub fn issue_28676() {
+ test();
+ }
+
+ fn test_62350() {
+ use std::ptr;
+ unsafe {
+ let null = ptr::null();
+ let q = QuadFloats {
+ a: 10.2,
+ b: 20.3,
+ c: 30.4,
+ d: 40.5
+ };
+ assert_eq!(
+ get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q),
+ q.c,
+ );
+ }
+ }
+
+ pub fn issue_62350() {
+ test_62350();
+ }
+
+ fn test1() {
+ unsafe {
+ let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa,
+ b: 0xbbbb_bbbb_bbbb_bbbb,
+ c: 0xcccc_cccc_cccc_cccc,
+ d: 0xdddd_dddd_dddd_dddd };
+ let qq = rust_dbg_abi_1(q);
+ println!("a: {:x}", qq.a as usize);
+ println!("b: {:x}", qq.b as usize);
+ println!("c: {:x}", qq.c as usize);
+ println!("d: {:x}", qq.d as usize);
+ assert_eq!(qq.a, q.c + 1);
+ assert_eq!(qq.b, q.d - 1);
+ assert_eq!(qq.c, q.a + 1);
+ assert_eq!(qq.d, q.b - 1);
+ }
+ }
+
+ fn test2() {
+ unsafe {
+ let f = Floats { a: 1.234567890e-15_f64,
+ b: 0b_1010_1010,
+ c: 1.0987654321e-15_f64 };
+ let ff = rust_dbg_abi_2(f);
+ println!("a: {}", ff.a as f64);
+ println!("b: {}", ff.b as usize);
+ println!("c: {}", ff.c as f64);
+ assert_eq!(ff.a, f.c + 1.0f64);
+ assert_eq!(ff.b, 0xff);
+ assert_eq!(ff.c, f.a - 1.0f64);
+ }
+ }
+
+ pub fn struct_return() {
+ test1();
+ test2();
+ }
+
+ pub fn enum_passing_and_return_pair() {
+ let some_u64u64 = unsafe { rust_dbg_new_some_u64u64(10, 20) };
+ if let U8TaggedEnumOptionU64U64::Some(a, b) = some_u64u64 {
+ assert_eq!(10, a);
+ assert_eq!(20, b);
+ } else {
+ panic!("unexpected none");
+ }
+
+ let none_u64u64 = unsafe { rust_dbg_new_none_u64u64() };
+ if let U8TaggedEnumOptionU64U64::Some(_,_) = none_u64u64 {
+ panic!("unexpected some");
+ }
+
+ let mut a: u64 = 0;
+ let mut b: u64 = 0;
+ let r = unsafe {
+ rust_dbg_unpack_option_u64u64(some_u64u64, &mut a as *mut _, &mut b as *mut _)
+ };
+ assert_eq!(1, r);
+ assert_eq!(10, a);
+ assert_eq!(20, b);
+
+ let mut a: u64 = 0;
+ let mut b: u64 = 0;
+ let r = unsafe {
+ rust_dbg_unpack_option_u64u64(none_u64u64, &mut a as *mut _, &mut b as *mut _)
+ };
+ assert_eq!(0, r);
+ assert_eq!(0, a);
+ assert_eq!(0, b);
+ }
+
+ pub fn enum_passing_and_return() {
+ let some_u64 = unsafe { rust_dbg_new_some_u64(10) };
+ if let U8TaggedEnumOptionU64::Some(v) = some_u64 {
+ assert_eq!(10, v);
+ } else {
+ panic!("unexpected none");
+ }
+
+ let none_u64 = unsafe { rust_dbg_new_none_u64() };
+ if let U8TaggedEnumOptionU64::Some(_) = none_u64 {
+ panic!("unexpected some");
+ }
+
+ let mut target: u64 = 0;
+ let r = unsafe { rust_dbg_unpack_option_u64(some_u64, &mut target as *mut _) };
+ assert_eq!(1, r);
+ assert_eq!(10, target);
+
+ let mut target: u64 = 0;
+ let r = unsafe { rust_dbg_unpack_option_u64(none_u64, &mut target as *mut _) };
+ assert_eq!(0, r);
+ assert_eq!(0, target);
+ }
+}
+
+#[cfg(target_arch = "x86_64")]
+fn main() {
+ use tests::*;
+ cabi_int_widening();
+ extern_pass_char();
+ extern_pass_u32();
+ extern_pass_u64();
+ extern_pass_double();
+ extern_pass_empty();
+ extern_pass_twou8s();
+ extern_pass_twou16s();
+ extern_pass_twou32s();
+ extern_pass_twou64s();
+ extern_return_twou8s();
+ extern_return_twou16s();
+ extern_return_twou32s();
+ extern_return_twou64s();
+ foreign_fn_with_byval();
+ issue_28676();
+ issue_62350();
+ struct_return();
+ enum_passing_and_return_pair();
+ enum_passing_and_return();
+}
+
+#[cfg(not(target_arch = "x86_64"))]
+fn main() {
+
+}