Add non-C-like enumeration tests on Rust->C calls to the abi-sysv64-arg-passing test.

This commit is contained in:
John VanEnk 2020-01-22 13:07:03 -08:00 committed by Eduard-Mihai Burtescu
parent 3b23b9864c
commit 1d28952631
2 changed files with 157 additions and 0 deletions

View File

@ -300,3 +300,87 @@ __int128 sub(__int128 a, __int128 b) {
} }
#endif #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");
}
}

View File

@ -92,6 +92,18 @@ mod tests {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Floats { a: f64, b: u8, c: f64 } 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")] #[link(name = "rust_test_helpers", kind = "static")]
extern "sysv64" { extern "sysv64" {
pub fn rust_int8_to_int32(_: i8) -> i32; pub fn rust_int8_to_int32(_: i8) -> i32;
@ -125,6 +137,12 @@ mod tests {
) -> f32; ) -> f32;
pub fn rust_dbg_abi_1(q: Quad) -> Quad; pub fn rust_dbg_abi_1(q: Quad) -> Quad;
pub fn rust_dbg_abi_2(f: Floats) -> Floats; 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() { pub fn cabi_int_widening() {
@ -336,6 +354,59 @@ mod tests {
test1(); test1();
test2(); 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")] #[cfg(target_arch = "x86_64")]
@ -359,6 +430,8 @@ fn main() {
issue_28676(); issue_28676();
issue_62350(); issue_62350();
struct_return(); struct_return();
enum_passing_and_return_pair();
enum_passing_and_return();
} }
#[cfg(not(target_arch = "x86_64"))] #[cfg(not(target_arch = "x86_64"))]