mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
move has_repr to layout, handle repr(transparent) properly
This commit is contained in:
parent
65d11b5c65
commit
00b3eca0df
@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -755,6 +755,7 @@ where
|
||||
largest_niche: None,
|
||||
align: tcx.data_layout.i8_align,
|
||||
size: Size::ZERO,
|
||||
has_repr_align: false,
|
||||
})
|
||||
}
|
||||
|
||||
@ -1104,15 +1105,6 @@ where
|
||||
fn is_unit(this: TyAndLayout<'tcx>) -> bool {
|
||||
matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
|
||||
}
|
||||
|
||||
fn repr_options(this: TyAndLayout<'tcx>) -> ReprOptions {
|
||||
match *this.ty.kind() {
|
||||
ty::Adt(def, ..) => def.repr(),
|
||||
_ => {
|
||||
bug!("TyAndLayout::repr_options({:?}): not applicable", this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates whether a function's ABI can unwind or not.
|
||||
|
@ -63,8 +63,8 @@ where
|
||||
|
||||
if t.is_like_msvc
|
||||
&& arg.layout.is_adt()
|
||||
&& let Some(requested_align) = arg.layout.repr_options().align
|
||||
&& requested_align > align_4
|
||||
&& arg.layout.has_repr_align
|
||||
&& arg.layout.align.abi > align_4
|
||||
{
|
||||
// MSVC has special rules for overaligned arguments: https://reviews.llvm.org/D72114.
|
||||
// Summarized here:
|
||||
@ -72,11 +72,6 @@ where
|
||||
// - For backwards compatibility, arguments with natural alignment > 4 are still passed
|
||||
// on stack (via `byval`). For example, this includes `double`, `int64_t`,
|
||||
// and structs containing them, provided they lack an explicit alignment attribute.
|
||||
assert!(arg.layout.align.abi >= requested_align,
|
||||
"abi alignment {:?} less than requested alignment {:?}",
|
||||
arg.layout.align.abi,
|
||||
requested_align
|
||||
);
|
||||
arg.make_indirect();
|
||||
} else if arg.layout.is_aggregate() {
|
||||
// We need to compute the alignment of the `byval` argument. The rules can be found in
|
||||
|
@ -55,7 +55,6 @@ pub trait TyAbiInterface<'a, C>: Sized {
|
||||
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
|
||||
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
|
||||
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
|
||||
fn repr_options(this: TyAndLayout<'a, Self>) -> ReprOptions;
|
||||
}
|
||||
|
||||
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
@ -126,13 +125,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
Ty::is_unit(self)
|
||||
}
|
||||
|
||||
pub fn repr_options<C>(self) -> ReprOptions
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C>,
|
||||
{
|
||||
Ty::repr_options(self)
|
||||
}
|
||||
|
||||
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C>,
|
||||
|
@ -258,6 +258,7 @@ fn layout_of_uncached<'tcx>(
|
||||
largest_niche,
|
||||
align: element.align,
|
||||
size,
|
||||
has_repr_align: false,
|
||||
})
|
||||
}
|
||||
ty::Slice(element) => {
|
||||
@ -269,6 +270,7 @@ fn layout_of_uncached<'tcx>(
|
||||
largest_niche: None,
|
||||
align: element.align,
|
||||
size: Size::ZERO,
|
||||
has_repr_align: false,
|
||||
})
|
||||
}
|
||||
ty::Str => tcx.mk_layout(LayoutS {
|
||||
@ -278,6 +280,7 @@ fn layout_of_uncached<'tcx>(
|
||||
largest_niche: None,
|
||||
align: dl.i8_align,
|
||||
size: Size::ZERO,
|
||||
has_repr_align: false,
|
||||
}),
|
||||
|
||||
// Odd unit types.
|
||||
@ -431,6 +434,7 @@ fn layout_of_uncached<'tcx>(
|
||||
largest_niche: e_ly.largest_niche,
|
||||
size,
|
||||
align,
|
||||
has_repr_align: false,
|
||||
})
|
||||
}
|
||||
|
||||
@ -879,6 +883,7 @@ fn generator_layout<'tcx>(
|
||||
largest_niche: prefix.largest_niche,
|
||||
size,
|
||||
align,
|
||||
has_repr_align: false,
|
||||
});
|
||||
debug!("generator layout ({:?}): {:#?}", ty, layout);
|
||||
Ok(layout)
|
||||
|
Loading…
Reference in New Issue
Block a user