Skip to content

Commit 31abdb2

Browse files
committed
Also emit noundef for #[repr(transparent)] structs/enums containing array immediate eligble arguments
1 parent 699eea1 commit 31abdb2

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

compiler/rustc_ty_utils/src/abi.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -786,8 +786,19 @@ fn fn_abi_adjust_for_abi<'tcx>(
786786
arg.cast_to(Reg { kind: RegKind::Integer, size });
787787

788788
// Let's see if we can add a `noundef`. This is only legal for arrays, definitely
789-
// not for unions.
790-
if arg.layout.ty.is_array() {
789+
// not for unions. This is also legal for `#[repr(transparent)] struct` or
790+
// `#[repr(transparent)] enum` containing array.
791+
let is_transparent_array =
792+
if arg.layout.is_transparent::<LayoutCx<'tcx, TyCtxt<'tcx>>>()
793+
&& let Some((_, layout)) = arg.layout.non_1zst_field(cx)
794+
&& layout.ty.is_array()
795+
{
796+
true
797+
} else {
798+
false
799+
};
800+
801+
if arg.layout.ty.is_array() || is_transparent_array {
791802
// Fixup arg attribute with `noundef`.
792803
let PassMode::Cast { ref mut cast, .. } = &mut arg.mode else {
793804
bug!("this cannot fail because of the previous cast_to `Reg`");

tests/codegen/array-immediate-param-noundef.rs

+20
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,23 @@ pub fn replace_short_array_u8x3(r: &mut [u8; 3], v: [u8; 3]) -> [u8; 3] {
7373
pub fn replace_short_array_u8x8(r: &mut [u8; 8], v: [u8; 8]) -> [u8; 8] {
7474
std::mem::replace(r, v)
7575
}
76+
77+
#[repr(transparent)]
78+
pub struct Foo([u8; 4]);
79+
80+
// CHECK: define noundef i32 @replace_repr_transparent_struct_short_array(ptr noalias noundef align 1 dereferenceable(4) %r, i32 noundef %0)
81+
#[no_mangle]
82+
pub fn replace_repr_transparent_struct_short_array(r: &mut Foo, v: Foo) -> Foo {
83+
std::mem::replace(r, v)
84+
}
85+
86+
#[repr(transparent)]
87+
pub enum Bar {
88+
Default([u8; 4])
89+
}
90+
91+
// CHECK: define noundef i32 @replace_repr_transparent_enum_short_array(ptr noalias noundef align 1 dereferenceable(4) %r, i32 noundef %0)
92+
#[no_mangle]
93+
pub fn replace_repr_transparent_enum_short_array(r: &mut Bar, v: Bar) -> Bar {
94+
std::mem::replace(r, v)
95+
}

0 commit comments

Comments
 (0)