Skip to content

Commit c2b0ca7

Browse files
committed
more ABI compat tests
1 parent 9db09c5 commit c2b0ca7

File tree

1 file changed

+48
-12
lines changed

1 file changed

+48
-12
lines changed

src/tools/miri/tests/pass/function_calls/abi_compat.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,89 @@ use std::mem;
33
use std::num;
44
use std::simd;
55

6-
fn test_abi_compat<T, U>(t: T, u: U) {
6+
#[derive(Copy, Clone)]
7+
struct Zst;
8+
9+
fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
710
fn id<T>(x: T) -> T {
811
x
912
}
13+
extern "C" fn id_c<T>(x: T) -> T {
14+
x
15+
}
1016

1117
// This checks ABI compatibility both for arguments and return values,
1218
// in both directions.
1319
let f: fn(T) -> T = id;
1420
let f: fn(U) -> U = unsafe { std::mem::transmute(f) };
15-
drop(f(u));
16-
21+
let _val = f(u);
1722
let f: fn(U) -> U = id;
1823
let f: fn(T) -> T = unsafe { std::mem::transmute(f) };
19-
drop(f(t));
24+
let _val = f(t);
25+
26+
// And then we do the same for `extern "C"`.
27+
let f: extern "C" fn(T) -> T = id_c;
28+
let f: extern "C" fn(U) -> U = unsafe { std::mem::transmute(f) };
29+
let _val = f(u);
30+
let f: extern "C" fn(U) -> U = id_c;
31+
let f: extern "C" fn(T) -> T = unsafe { std::mem::transmute(f) };
32+
let _val = f(t);
2033
}
2134

2235
/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
2336
fn test_abi_newtype<T: Copy>(t: T) {
2437
#[repr(transparent)]
38+
#[derive(Copy, Clone)]
2539
struct Wrapper1<T>(T);
2640
#[repr(transparent)]
41+
#[derive(Copy, Clone)]
2742
struct Wrapper2<T>(T, ());
2843
#[repr(transparent)]
44+
#[derive(Copy, Clone)]
2945
struct Wrapper2a<T>((), T);
3046
#[repr(transparent)]
31-
struct Wrapper3<T>(T, [u8; 0]);
47+
#[derive(Copy, Clone)]
48+
struct Wrapper3<T>(Zst, T, [u8; 0]);
3249

3350
test_abi_compat(t, Wrapper1(t));
3451
test_abi_compat(t, Wrapper2(t, ()));
3552
test_abi_compat(t, Wrapper2a((), t));
36-
test_abi_compat(t, Wrapper3(t, []));
53+
test_abi_compat(t, Wrapper3(Zst, t, []));
54+
test_abi_compat(t, mem::MaybeUninit::new(t)); // MaybeUninit is `repr(transparent)`
3755
}
3856

3957
fn main() {
58+
// Here we check:
59+
// - unsigned vs signed integer is allowed
60+
// - u32/i32 vs char is allowed
61+
// - u32 vs NonZeroU32/Option<NonZeroU32> is allowed
62+
// - reference vs raw pointer is allowed
63+
// - references to things of the same size and alignment are allowed
64+
// These are very basic tests that should work on all ABIs. However it is not clear that any of
65+
// these would be stably guaranteed. Code that relies on this is equivalent to code that relies
66+
// on the layout of `repr(Rust)` types. They are also fragile: the same mismatches in the fields
67+
// of a struct (even with `repr(C)`) will not always be accepted by Miri.
68+
test_abi_compat(0u32, 0i32);
69+
test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1));
4070
test_abi_compat(0u32, 'x');
41-
test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
42-
test_abi_compat(0u32, mem::MaybeUninit::new(0u32));
71+
test_abi_compat(0i32, 'x');
4372
test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
4473
test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
45-
test_abi_compat(0u32, 0i32);
46-
test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1));
74+
test_abi_compat(&0u32, &0u32 as *const u32);
75+
test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
4776
// Note that `bool` and `u8` are *not* compatible, at least on x86-64!
4877
// One of them has `arg_ext: Zext`, the other does not.
4978

79+
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
80+
// with the wrapped field.
81+
test_abi_newtype(());
82+
// FIXME: this still fails! test_abi_newtype(Zst);
5083
test_abi_newtype(0u32);
5184
test_abi_newtype(0f32);
5285
test_abi_newtype((0u32, 1u32, 2u32));
53-
test_abi_newtype([0u32, 1u32, 2u32]);
54-
test_abi_newtype([0i32; 0]);
86+
// FIXME: skipping the array tests on mips64 due to https://github.com/rust-lang/rust/issues/115404
87+
if !cfg!(target_arch = "mips64") {
88+
test_abi_newtype([0u32, 1u32, 2u32]);
89+
test_abi_newtype([0i32; 0]);
90+
}
5591
}

0 commit comments

Comments
 (0)