-
Notifications
You must be signed in to change notification settings - Fork 353
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #3046 - RalfJung:rustup, r=RalfJung
Rustup also more ABI compat tests
- Loading branch information
Showing
18 changed files
with
160 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
008c21c9779fd1e3632d9fe908b8afc0c421b26c | ||
dca2d1ff00bf96d244b1bb9a2117a92ec50ac71d |
16 changes: 16 additions & 0 deletions
16
tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#![feature(portable_simd)] | ||
|
||
// Some targets treat arrays and structs very differently. We would probably catch that on those | ||
// targets since we check the `PassMode`; here we ensure that we catch it on *all* targets | ||
// (in particular, on x86-64 the pass mode is `Indirect` for both of these). | ||
struct S(i32, i32, i32, i32); | ||
type A = [i32; 4]; | ||
|
||
fn main() { | ||
fn f(_: S) {} | ||
|
||
// These two types have the same size but are still not compatible. | ||
let g = unsafe { std::mem::transmute::<fn(S), fn(A)>(f) }; | ||
|
||
g(Default::default()) //~ ERROR: calling a function with argument of type S passing data of type [i32; 4] | ||
} |
15 changes: 15 additions & 0 deletions
15
tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
error: Undefined Behavior: calling a function with argument of type S passing data of type [i32; 4] | ||
--> $DIR/abi_mismatch_array_vs_struct.rs:LL:CC | ||
| | ||
LL | g(Default::default()) | ||
| ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S passing data of type [i32; 4] | ||
| | ||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior | ||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information | ||
= note: BACKTRACE: | ||
= note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC | ||
|
||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
fn main() { | ||
fn f(_: f32) {} | ||
|
||
let g = unsafe { std::mem::transmute::<fn(f32), fn(i32)>(f) }; | ||
|
||
g(42) //~ ERROR: calling a function with argument of type f32 passing data of type i32 | ||
} |
15 changes: 15 additions & 0 deletions
15
tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
error: Undefined Behavior: calling a function with argument of type f32 passing data of type i32 | ||
--> $DIR/abi_mismatch_int_vs_float.rs:LL:CC | ||
| | ||
LL | g(42) | ||
| ^^^^^ calling a function with argument of type f32 passing data of type i32 | ||
| | ||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior | ||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information | ||
= note: BACKTRACE: | ||
= note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC | ||
|
||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | ||
|
||
error: aborting due to previous error | ||
|
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
...ail/function_pointers/cast_fn_ptr4.stderr → ..._pointers/abi_mismatch_raw_pointer.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
...ail/function_pointers/cast_fn_ptr5.stderr → ..._pointers/abi_mismatch_return_type.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
...ail/function_pointers/cast_fn_ptr2.stderr → ...ction_pointers/abi_mismatch_simple.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
...ail/function_pointers/cast_fn_ptr3.stderr → ...pointers/abi_mismatch_too_few_args.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
...ail/function_pointers/cast_fn_ptr1.stderr → ...ointers/abi_mismatch_too_many_args.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#![feature(portable_simd)] | ||
use std::simd; | ||
|
||
fn main() { | ||
fn f(_: simd::u32x8) {} | ||
|
||
// These two vector types have the same size but are still not compatible. | ||
let g = unsafe { std::mem::transmute::<fn(simd::u32x8), fn(simd::u64x4)>(f) }; | ||
|
||
g(Default::default()) //~ ERROR: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
error: Undefined Behavior: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4> | ||
--> $DIR/abi_mismatch_vector.rs:LL:CC | ||
| | ||
LL | g(Default::default()) | ||
| ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4> | ||
| | ||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior | ||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information | ||
= note: BACKTRACE: | ||
= note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC | ||
|
||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,91 @@ | ||
#![feature(portable_simd)] | ||
use std::mem; | ||
use std::num; | ||
use std::simd; | ||
|
||
fn test_abi_compat<T, U>(t: T, u: U) { | ||
#[derive(Copy, Clone)] | ||
struct Zst; | ||
|
||
fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) { | ||
fn id<T>(x: T) -> T { | ||
x | ||
} | ||
extern "C" fn id_c<T>(x: T) -> T { | ||
x | ||
} | ||
|
||
// This checks ABI compatibility both for arguments and return values, | ||
// in both directions. | ||
let f: fn(T) -> T = id; | ||
let f: fn(U) -> U = unsafe { std::mem::transmute(f) }; | ||
drop(f(u)); | ||
|
||
let _val = f(u); | ||
let f: fn(U) -> U = id; | ||
let f: fn(T) -> T = unsafe { std::mem::transmute(f) }; | ||
drop(f(t)); | ||
let _val = f(t); | ||
|
||
// And then we do the same for `extern "C"`. | ||
let f: extern "C" fn(T) -> T = id_c; | ||
let f: extern "C" fn(U) -> U = unsafe { std::mem::transmute(f) }; | ||
let _val = f(u); | ||
let f: extern "C" fn(U) -> U = id_c; | ||
let f: extern "C" fn(T) -> T = unsafe { std::mem::transmute(f) }; | ||
let _val = f(t); | ||
} | ||
|
||
/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`. | ||
fn test_abi_newtype<T: Copy>(t: T) { | ||
#[repr(transparent)] | ||
#[derive(Copy, Clone)] | ||
struct Wrapper1<T>(T); | ||
#[repr(transparent)] | ||
#[derive(Copy, Clone)] | ||
struct Wrapper2<T>(T, ()); | ||
#[repr(transparent)] | ||
#[derive(Copy, Clone)] | ||
struct Wrapper2a<T>((), T); | ||
#[repr(transparent)] | ||
#[derive(Copy, Clone)] | ||
struct Wrapper3<T>(Zst, T, [u8; 0]); | ||
|
||
test_abi_compat(t, Wrapper1(t)); | ||
test_abi_compat(t, Wrapper2(t, ())); | ||
test_abi_compat(t, Wrapper2a((), t)); | ||
test_abi_compat(t, Wrapper3(Zst, t, [])); | ||
test_abi_compat(t, mem::MaybeUninit::new(t)); // MaybeUninit is `repr(transparent)` | ||
} | ||
|
||
fn main() { | ||
// Here we check: | ||
// - unsigned vs signed integer is allowed | ||
// - u32/i32 vs char is allowed | ||
// - u32 vs NonZeroU32/Option<NonZeroU32> is allowed | ||
// - reference vs raw pointer is allowed | ||
// - references to things of the same size and alignment are allowed | ||
// These are very basic tests that should work on all ABIs. However it is not clear that any of | ||
// these would be stably guaranteed. Code that relies on this is equivalent to code that relies | ||
// on the layout of `repr(Rust)` types. They are also fragile: the same mismatches in the fields | ||
// of a struct (even with `repr(C)`) will not always be accepted by Miri. | ||
test_abi_compat(0u32, 0i32); | ||
test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1)); | ||
test_abi_compat(0u32, 'x'); | ||
test_abi_compat(&0u32, &([true; 4], [0u32; 0])); | ||
test_abi_compat(0u32, mem::MaybeUninit::new(0u32)); | ||
test_abi_compat(0i32, 'x'); | ||
test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap()); | ||
test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap())); | ||
test_abi_compat(0u32, 0i32); | ||
// Note that `bool` and `u8` are *not* compatible! | ||
test_abi_compat(&0u32, &0u32 as *const u32); | ||
test_abi_compat(&0u32, &([true; 4], [0u32; 0])); | ||
// Note that `bool` and `u8` are *not* compatible, at least on x86-64! | ||
// One of them has `arg_ext: Zext`, the other does not. | ||
|
||
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible | ||
// with the wrapped field. | ||
test_abi_newtype(()); | ||
// FIXME: this still fails! test_abi_newtype(Zst); | ||
test_abi_newtype(0u32); | ||
test_abi_newtype(0f32); | ||
test_abi_newtype((0u32, 1u32, 2u32)); | ||
// FIXME: skipping the array tests on mips64 due to https://github.com/rust-lang/rust/issues/115404 | ||
if !cfg!(target_arch = "mips64") { | ||
test_abi_newtype([0u32, 1u32, 2u32]); | ||
test_abi_newtype([0i32; 0]); | ||
} | ||
} |