blob: 0d51ceb72ca44bf7a43e1a7201cf762cda10b33e [file]
// Verify that `PassMode::Cast` arguments/returns in the Rust ABI carry `noundef`
// when the original layout provably contains no uninit bytes, and correctly omit
// it when uninit bytes or padding may be present.
//
// See <https://github.com/rust-lang/rust/issues/123183>.
//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
//@ only-64bit
#![crate_type = "lib"]
use std::mem::MaybeUninit;
// CHECK-LABEL: @arg_array_u32x2(
// CHECK-SAME: i64 noundef
#[no_mangle]
pub fn arg_array_u32x2(v: [u32; 2]) -> u32 {
v[0]
}
// CHECK-LABEL: @arg_array_u8x4(
// CHECK-SAME: i32 noundef
#[no_mangle]
pub fn arg_array_u8x4(v: [u8; 4]) -> u8 {
v[0]
}
// CHECK-LABEL: @arg_nested_array(
// CHECK-SAME: i64 noundef
#[no_mangle]
pub fn arg_nested_array(v: [[u8; 2]; 4]) -> u8 {
v[0][0]
}
// CHECK-LABEL: @arg_array_bool(
// CHECK-SAME: i64 noundef
#[no_mangle]
pub fn arg_array_bool(v: [bool; 8]) -> bool {
v[0]
}
struct FourU8 {
a: u8,
b: u8,
c: u8,
d: u8,
}
// CHECK-LABEL: @arg_four_u8(
// CHECK-SAME: i32 noundef
#[no_mangle]
pub fn arg_four_u8(v: FourU8) -> u8 {
v.a
}
struct Wrapper([u32; 2]);
// CHECK-LABEL: @arg_newtype_wrapper(
// CHECK-SAME: i64 noundef
#[no_mangle]
pub fn arg_newtype_wrapper(v: Wrapper) -> u32 {
(v.0)[0]
}
enum SingleVariant {
Only([u32; 2]),
}
// CHECK-LABEL: @arg_single_variant_enum(
// CHECK-SAME: i64 noundef
#[no_mangle]
pub fn arg_single_variant_enum(v: SingleVariant) -> u32 {
match v {
SingleVariant::Only(a) => a[0],
}
}
struct ContainsScalarPair {
a: (u16, u16),
b: u32,
}
// CHECK-LABEL: @arg_contains_scalar_pair(
// CHECK-SAME: i64 noundef
#[no_mangle]
pub fn arg_contains_scalar_pair(v: ContainsScalarPair) -> u32 {
v.b
}
// CHECK: define noundef i64 @ret_array_u32x2(
#[no_mangle]
pub fn ret_array_u32x2(x: u32, y: u32) -> [u32; 2] {
[x, y]
}
// CHECK-LABEL: @arg_maybeuninit_u8x8(
// CHECK-SAME: i64 %
#[no_mangle]
pub fn arg_maybeuninit_u8x8(v: [MaybeUninit<u8>; 8]) -> MaybeUninit<u8> {
v[0]
}
enum MultiVariant {
A(u8),
B(u16),
C,
}
// CHECK-LABEL: @arg_multi_variant_enum(
// CHECK-SAME: i32 %
#[no_mangle]
pub fn arg_multi_variant_enum(v: MultiVariant) -> u8 {
match v {
MultiVariant::A(x) => x,
MultiVariant::B(_) | MultiVariant::C => 0,
}
}
#[repr(C)]
struct HasFieldGap {
a: u8,
b: u16,
c: u8,
}
// CHECK-LABEL: @arg_struct_field_gap(
// CHECK-SAME: i48 %
#[no_mangle]
pub fn arg_struct_field_gap(v: HasFieldGap) -> u8 {
v.a
}
#[repr(C)]
struct HasPaddedPairField {
a: (u8, u16),
b: u8,
}
// CHECK-LABEL: @arg_struct_padded_pair_field(
// CHECK-SAME: i48 %
#[no_mangle]
pub fn arg_struct_padded_pair_field(v: HasPaddedPairField) -> u8 {
v.b
}
#[repr(C)]
struct HasUndefPairField {
a: (MaybeUninit<u16>, u16),
b: u32,
}
// CHECK-LABEL: @arg_struct_undef_pair_field(
// CHECK-SAME: i64 %
#[no_mangle]
pub fn arg_struct_undef_pair_field(v: HasUndefPairField) -> u32 {
v.b
}
// CHECK-LABEL: @arg_triple_maybeuninit_u8(
// CHECK-SAME: i24 %
#[no_mangle]
pub fn arg_triple_maybeuninit_u8(
v: (MaybeUninit<u8>, MaybeUninit<u8>, MaybeUninit<u8>),
) -> MaybeUninit<u8> {
v.0
}
#[repr(C)]
struct HasTrailingPadding {
x: u32,
y: u16,
z: u8,
}
// CHECK-LABEL: @arg_struct_trailing_pad(
// CHECK-SAME: i64 %
#[no_mangle]
pub fn arg_struct_trailing_pad(v: HasTrailingPadding) -> u32 {
v.x
}
// CHECK-LABEL: @arg_tuple_i8_i16(
// CHECK-SAME: i8 noundef
// CHECK-SAME: i16 noundef
#[no_mangle]
pub fn arg_tuple_i8_i16(v: (i8, i16)) -> i8 {
v.0
}
// CHECK-LABEL: @arg_tuple_i16_maybeuninit(
// CHECK-SAME: i16 noundef
// CHECK-SAME: i16 %
#[no_mangle]
pub fn arg_tuple_i16_maybeuninit(v: (i16, MaybeUninit<i16>)) -> i16 {
v.0
}
// CHECK-LABEL: @arg_result_i32(
// CHECK-SAME: i32 noundef
// CHECK-SAME: i32 noundef
#[no_mangle]
pub fn arg_result_i32(v: Result<i32, i32>) -> i32 {
match v {
Ok(x) | Err(x) => x,
}
}