Skip to content

Commit 1d28952

Browse files
sw17cheddyb
authored andcommitted
Add non-C-like enumeration tests on Rust->C calls to the abi-sysv64-arg-passing test.
1 parent 3b23b98 commit 1d28952

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

src/test/auxiliary/rust_test_helpers.c

+84
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,87 @@ __int128 sub(__int128 a, __int128 b) {
300300
}
301301

302302
#endif
303+
304+
#define OPTION_TAG_NONE (0)
305+
#define OPTION_TAG_SOME (1)
306+
307+
struct U8TaggedEnumOptionU64 {
308+
uint8_t tag;
309+
union {
310+
uint64_t some;
311+
};
312+
};
313+
314+
struct U8TaggedEnumOptionU64
315+
rust_dbg_new_some_u64(uint64_t some) {
316+
struct U8TaggedEnumOptionU64 r = {
317+
.tag = OPTION_TAG_SOME,
318+
.some = some,
319+
};
320+
return r;
321+
}
322+
323+
struct U8TaggedEnumOptionU64
324+
rust_dbg_new_none_u64(void) {
325+
struct U8TaggedEnumOptionU64 r = {
326+
.tag = OPTION_TAG_NONE,
327+
};
328+
return r;
329+
}
330+
331+
int32_t
332+
rust_dbg_unpack_option_u64(struct U8TaggedEnumOptionU64 o, uint64_t *into) {
333+
assert(into);
334+
switch (o.tag) {
335+
case OPTION_TAG_SOME:
336+
*into = o.some;
337+
return 1;
338+
case OPTION_TAG_NONE:
339+
return 0;
340+
default:
341+
assert(0 && "unexpected tag");
342+
}
343+
}
344+
345+
struct U8TaggedEnumOptionU64U64 {
346+
uint8_t tag;
347+
union {
348+
struct {
349+
uint64_t a;
350+
uint64_t b;
351+
} some;
352+
};
353+
};
354+
355+
struct U8TaggedEnumOptionU64U64
356+
rust_dbg_new_some_u64u64(uint64_t a, uint64_t b) {
357+
struct U8TaggedEnumOptionU64U64 r = {
358+
.tag = OPTION_TAG_SOME,
359+
.some = { .a = a, .b = b },
360+
};
361+
return r;
362+
}
363+
364+
struct U8TaggedEnumOptionU64U64
365+
rust_dbg_new_none_u64u64(void) {
366+
struct U8TaggedEnumOptionU64U64 r = {
367+
.tag = OPTION_TAG_NONE,
368+
};
369+
return r;
370+
}
371+
372+
int32_t
373+
rust_dbg_unpack_option_u64u64(struct U8TaggedEnumOptionU64U64 o, uint64_t *a, uint64_t *b) {
374+
assert(a);
375+
assert(b);
376+
switch (o.tag) {
377+
case OPTION_TAG_SOME:
378+
*a = o.some.a;
379+
*b = o.some.b;
380+
return 1;
381+
case OPTION_TAG_NONE:
382+
return 0;
383+
default:
384+
assert(0 && "unexpected tag");
385+
}
386+
}

src/test/ui/abi/abi-sysv64-arg-passing.rs

+73
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ mod tests {
9292
#[derive(Copy, Clone)]
9393
pub struct Floats { a: f64, b: u8, c: f64 }
9494

95+
#[repr(C, u8)]
96+
pub enum U8TaggedEnumOptionU64U64 {
97+
None,
98+
Some(u64,u64),
99+
}
100+
101+
#[repr(C, u8)]
102+
pub enum U8TaggedEnumOptionU64 {
103+
None,
104+
Some(u64),
105+
}
106+
95107
#[link(name = "rust_test_helpers", kind = "static")]
96108
extern "sysv64" {
97109
pub fn rust_int8_to_int32(_: i8) -> i32;
@@ -125,6 +137,12 @@ mod tests {
125137
) -> f32;
126138
pub fn rust_dbg_abi_1(q: Quad) -> Quad;
127139
pub fn rust_dbg_abi_2(f: Floats) -> Floats;
140+
pub fn rust_dbg_new_some_u64u64(a: u64, b: u64) -> U8TaggedEnumOptionU64U64;
141+
pub fn rust_dbg_new_none_u64u64() -> U8TaggedEnumOptionU64U64;
142+
pub fn rust_dbg_unpack_option_u64u64(o: U8TaggedEnumOptionU64U64, a: *mut u64, b: *mut u64) -> i32;
143+
pub fn rust_dbg_new_some_u64(some: u64) -> U8TaggedEnumOptionU64;
144+
pub fn rust_dbg_new_none_u64() -> U8TaggedEnumOptionU64;
145+
pub fn rust_dbg_unpack_option_u64(o: U8TaggedEnumOptionU64, v: *mut u64) -> i32;
128146
}
129147

130148
pub fn cabi_int_widening() {
@@ -336,6 +354,59 @@ mod tests {
336354
test1();
337355
test2();
338356
}
357+
358+
pub fn enum_passing_and_return_pair() {
359+
let some_u64u64 = unsafe { rust_dbg_new_some_u64u64(10, 20) };
360+
if let U8TaggedEnumOptionU64U64::Some(a, b) = some_u64u64 {
361+
assert_eq!(10, a);
362+
assert_eq!(20, b);
363+
} else {
364+
panic!("unexpected none");
365+
}
366+
367+
let none_u64u64 = unsafe { rust_dbg_new_none_u64u64() };
368+
if let U8TaggedEnumOptionU64U64::Some(_,_) = none_u64u64 {
369+
panic!("unexpected some");
370+
}
371+
372+
let mut a: u64 = 0;
373+
let mut b: u64 = 0;
374+
let r = unsafe { rust_dbg_unpack_option_u64u64(some_u64u64, &mut a as *mut _, &mut b as *mut _) };
375+
assert_eq!(1, r);
376+
assert_eq!(10, a);
377+
assert_eq!(20, b);
378+
379+
let mut a: u64 = 0;
380+
let mut b: u64 = 0;
381+
let r = unsafe { rust_dbg_unpack_option_u64u64(none_u64u64, &mut a as *mut _, &mut b as *mut _) };
382+
assert_eq!(0, r);
383+
assert_eq!(0, a);
384+
assert_eq!(0, b);
385+
}
386+
387+
pub fn enum_passing_and_return() {
388+
let some_u64 = unsafe { rust_dbg_new_some_u64(10) };
389+
if let U8TaggedEnumOptionU64::Some(v) = some_u64 {
390+
assert_eq!(10, v);
391+
} else {
392+
panic!("unexpected none");
393+
}
394+
395+
let none_u64 = unsafe { rust_dbg_new_none_u64() };
396+
if let U8TaggedEnumOptionU64::Some(_) = none_u64 {
397+
panic!("unexpected some");
398+
}
399+
400+
let mut target: u64 = 0;
401+
let r = unsafe { rust_dbg_unpack_option_u64(some_u64, &mut target as *mut _) };
402+
assert_eq!(1, r);
403+
assert_eq!(10, target);
404+
405+
let mut target: u64 = 0;
406+
let r = unsafe { rust_dbg_unpack_option_u64(none_u64, &mut target as *mut _) };
407+
assert_eq!(0, r);
408+
assert_eq!(0, target);
409+
}
339410
}
340411

341412
#[cfg(target_arch = "x86_64")]
@@ -359,6 +430,8 @@ fn main() {
359430
issue_28676();
360431
issue_62350();
361432
struct_return();
433+
enum_passing_and_return_pair();
434+
enum_passing_and_return();
362435
}
363436

364437
#[cfg(not(target_arch = "x86_64"))]

0 commit comments

Comments
 (0)