about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn VanEnk <vanenkj@gmail.com>2020-01-22 13:07:03 -0800
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2020-02-08 06:50:59 +0200
commit1d28952631b37f422a6c0bd9660c20b0b40f5bf9 (patch)
tree0d63e36ef4310db07fe6f96b28b72e91501da247
parent3b23b9864c07e47247c93d69e7ed8197c4cc9b37 (diff)
downloadrust-1d28952631b37f422a6c0bd9660c20b0b40f5bf9.tar.gz
rust-1d28952631b37f422a6c0bd9660c20b0b40f5bf9.zip
Add non-C-like enumeration tests on Rust->C calls to the abi-sysv64-arg-passing test.
-rw-r--r--src/test/auxiliary/rust_test_helpers.c84
-rw-r--r--src/test/ui/abi/abi-sysv64-arg-passing.rs73
2 files changed, 157 insertions, 0 deletions
diff --git a/src/test/auxiliary/rust_test_helpers.c b/src/test/auxiliary/rust_test_helpers.c
index b95b0ca1a89..a5299638e52 100644
--- a/src/test/auxiliary/rust_test_helpers.c
+++ b/src/test/auxiliary/rust_test_helpers.c
@@ -300,3 +300,87 @@ __int128 sub(__int128 a, __int128 b) {
 }
 
 #endif
+
+#define OPTION_TAG_NONE (0)
+#define OPTION_TAG_SOME (1)
+
+struct U8TaggedEnumOptionU64 {
+    uint8_t tag;
+    union {
+        uint64_t some;
+    };
+};
+
+struct U8TaggedEnumOptionU64
+rust_dbg_new_some_u64(uint64_t some) {
+    struct U8TaggedEnumOptionU64 r = {
+        .tag = OPTION_TAG_SOME,
+        .some = some,
+    };
+    return r;
+}
+
+struct U8TaggedEnumOptionU64
+rust_dbg_new_none_u64(void) {
+    struct U8TaggedEnumOptionU64 r = {
+        .tag = OPTION_TAG_NONE,
+    };
+    return r;
+}
+
+int32_t
+rust_dbg_unpack_option_u64(struct U8TaggedEnumOptionU64 o, uint64_t *into) {
+    assert(into);
+    switch (o.tag) {
+    case OPTION_TAG_SOME:
+        *into = o.some;
+        return 1;
+    case OPTION_TAG_NONE:
+        return 0;
+    default:
+        assert(0 && "unexpected tag");
+    }
+}
+
+struct U8TaggedEnumOptionU64U64 {
+    uint8_t tag;
+    union {
+        struct {
+	    uint64_t a;
+	    uint64_t b;
+	} some;
+    };
+};
+
+struct U8TaggedEnumOptionU64U64
+rust_dbg_new_some_u64u64(uint64_t a, uint64_t b) {
+    struct U8TaggedEnumOptionU64U64 r = {
+        .tag = OPTION_TAG_SOME,
+        .some = { .a = a, .b = b },
+    };
+    return r;
+}
+
+struct U8TaggedEnumOptionU64U64
+rust_dbg_new_none_u64u64(void) {
+    struct U8TaggedEnumOptionU64U64 r = {
+        .tag = OPTION_TAG_NONE,
+    };
+    return r;
+}
+
+int32_t
+rust_dbg_unpack_option_u64u64(struct U8TaggedEnumOptionU64U64 o, uint64_t *a, uint64_t *b) {
+    assert(a);
+    assert(b);
+    switch (o.tag) {
+    case OPTION_TAG_SOME:
+        *a = o.some.a;
+        *b = o.some.b;
+        return 1;
+    case OPTION_TAG_NONE:
+        return 0;
+    default:
+        assert(0 && "unexpected tag");
+    }
+}
diff --git a/src/test/ui/abi/abi-sysv64-arg-passing.rs b/src/test/ui/abi/abi-sysv64-arg-passing.rs
index d40006eb9b6..adb62ab698e 100644
--- a/src/test/ui/abi/abi-sysv64-arg-passing.rs
+++ b/src/test/ui/abi/abi-sysv64-arg-passing.rs
@@ -92,6 +92,18 @@ mod tests {
     #[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;
@@ -125,6 +137,12 @@ mod tests {
         ) -> 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() {
@@ -336,6 +354,59 @@ mod tests {
         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")]
@@ -359,6 +430,8 @@ fn main() {
     issue_28676();
     issue_62350();
     struct_return();
+    enum_passing_and_return_pair();
+    enum_passing_and_return();
 }
 
 #[cfg(not(target_arch = "x86_64"))]