1
Fork 0

move has_repr to layout, handle repr(transparent) properly

This commit is contained in:
Erik Desjardins 2023-06-11 13:43:49 -04:00
parent 65d11b5c65
commit 00b3eca0df
6 changed files with 34 additions and 25 deletions

View file

@ -40,6 +40,7 @@ pub trait LayoutCalculator {
largest_niche,
align,
size,
has_repr_align: false,
}
}
@ -122,6 +123,7 @@ pub trait LayoutCalculator {
largest_niche: None,
align: dl.i8_align,
size: Size::ZERO,
has_repr_align: false,
}
}
@ -422,6 +424,7 @@ pub trait LayoutCalculator {
largest_niche,
size,
align,
has_repr_align: repr.align.is_some(),
};
Some(TmpLayout { layout, variants: variant_layouts })
@ -691,6 +694,7 @@ pub trait LayoutCalculator {
abi,
align,
size,
has_repr_align: repr.align.is_some(),
};
let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
@ -809,6 +813,7 @@ pub trait LayoutCalculator {
largest_niche: None,
align,
size: size.align_to(align.abi),
has_repr_align: repr.align.is_some(),
})
}
}
@ -1036,6 +1041,7 @@ fn univariant(
inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect()
};
let size = min_size.align_to(align.abi);
let mut layout_of_single_non_zst_field = None;
let mut abi = Abi::Aggregate { sized };
// Unpack newtype ABIs and find scalar pairs.
if sized && size.bytes() > 0 {
@ -1045,6 +1051,8 @@ fn univariant(
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
// We have exactly one non-ZST field.
(Some((i, field)), None, None) => {
layout_of_single_non_zst_field = Some(field);
// Field fills the struct and it has a scalar or scalar pair ABI.
if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size()
{
@ -1102,6 +1110,11 @@ fn univariant(
if fields.iter().any(|f| f.abi().is_uninhabited()) {
abi = Abi::Uninhabited;
}
let has_repr_align = repr.align.is_some()
|| repr.transparent()
&& layout_of_single_non_zst_field.map_or(false, |l| l.has_repr_align());
Some(LayoutS {
variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Arbitrary { offsets, memory_index },
@ -1109,6 +1122,7 @@ fn univariant(
largest_niche,
align,
size,
has_repr_align,
})
}

View file

@ -1531,6 +1531,11 @@ pub struct LayoutS {
pub align: AbiAndPrefAlign,
pub size: Size,
/// True if the alignment was explicitly requested with `repr(align)`.
/// Only used on i686-windows, where the argument passing ABI is different when alignment is
/// requested, even if the requested alignment is equal to or less than the natural alignment.
pub has_repr_align: bool,
}
impl LayoutS {
@ -1545,6 +1550,7 @@ impl LayoutS {
largest_niche,
size,
align,
has_repr_align: false,
}
}
}
@ -1554,7 +1560,7 @@ impl fmt::Debug for LayoutS {
// This is how `Layout` used to print before it become
// `Interned<LayoutS>`. We print it like this to avoid having to update
// expected output in a lot of tests.
let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
let LayoutS { size, align, abi, fields, largest_niche, variants, has_repr_align } = self;
f.debug_struct("Layout")
.field("size", size)
.field("align", align)
@ -1562,6 +1568,7 @@ impl fmt::Debug for LayoutS {
.field("fields", fields)
.field("largest_niche", largest_niche)
.field("variants", variants)
.field("has_repr_align", has_repr_align)
.finish()
}
}
@ -1602,6 +1609,10 @@ impl<'a> Layout<'a> {
self.0.0.size
}
pub fn has_repr_align(self) -> bool {
self.0.0.has_repr_align
}
/// Whether the layout is from a type that implements [`std::marker::PointerLike`].
///
/// Currently, that means that the type is pointer-sized, pointer-aligned,