1use std::fmt::{self, Write};
2use std::num::NonZero;
3use std::ops::Deref;
4use std::range::{RangeFrom, RangeInclusive, RangeToInclusive};
5use std::{cmp, iter};
6
7use rustc_hashes::Hash64;
8use rustc_index::Idx;
9use rustc_index::bit_set::BitMatrix;
10use tracing::{debug, trace};
11
12use crate::{
13 AbiAlign, Align, BackendLaneCount, BackendRepr, FieldsShape, HasDataLayout, IndexSlice,
14 IndexVec, Integer, LayoutData, Niche, NicheOptimizations, NumScalableVectors, Primitive,
15 ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants,
16 WrappingRange,
17};
18
19mod coroutine;
20mod simple;
21
22#[cfg(feature = "nightly")]
23mod ty;
24
25#[cfg(feature = "nightly")]
26pub use ty::{Layout, TyAbiInterface, TyAndLayout};
27
28#[automatically_derived]impl ::core::marker::Copy for FieldIdx { }
impl FieldIdx {
#[doc = r" Maximum value the index can take, as a `u32`."]
pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
pub const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
pub const fn as_u32(self) -> u32 {
unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for FieldIdx {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for FieldIdx {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for FieldIdx {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for FieldIdx {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as
::std::iter::Step>::steps_between(&Self::index(*start),
&Self::index(*end))
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
#[inline]
fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_add(u);
(Self::from_usize(s), o)
}
#[inline]
fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_sub(u);
(Self::from_usize(s), o)
}
}
impl ::std::cmp::Ord for FieldIdx {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_u32().cmp(&other.as_u32())
}
}
impl ::std::cmp::PartialOrd for FieldIdx {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl ::rustc_data_structures::stable_hash::StableHash for FieldIdx {
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
hcx: &mut __Hcx,
hasher: &mut ::rustc_data_structures::stable_hash::StableHasher) {
self.as_u32().stable_hash(hcx, hasher)
}
}
impl From<FieldIdx> for u32 {
#[inline]
fn from(v: FieldIdx) -> u32 { v.as_u32() }
}
impl From<FieldIdx> for usize {
#[inline]
fn from(v: FieldIdx) -> usize { v.as_usize() }
}
impl From<usize> for FieldIdx {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for FieldIdx {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for FieldIdx {}
impl ::std::cmp::PartialEq for FieldIdx {
fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for FieldIdx { }
impl ::std::hash::Hash for FieldIdx {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for
FieldIdx {
fn decode(d: &mut D) -> Self { Self::from_u32(d.read_u32()) }
}
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for
FieldIdx {
fn encode(&self, e: &mut E) { e.emit_u32(self.as_u32()); }
}
impl ::std::fmt::Debug for FieldIdx {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("{0}", self.as_u32()))
}
}rustc_index::newtype_index! {
29 #[stable_hash]
51 #[encodable]
52 #[orderable]
53 #[gate_rustc_only]
54 pub struct FieldIdx {}
55}
56
57impl FieldIdx {
58 pub const ONE: FieldIdx = FieldIdx::from_u32(1);
62}
63
64#[automatically_derived]impl ::core::marker::Copy for VariantIdx { }
#[doc = " Equivalent to `VariantIdx(0)`."]
pub const FIRST_VARIANT: VariantIdx = VariantIdx::from_u32(0);
impl VariantIdx {
#[doc = r" Maximum value the index can take, as a `u32`."]
pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
pub const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
pub const fn as_u32(self) -> u32 {
unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for VariantIdx {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for VariantIdx {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for VariantIdx {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for VariantIdx {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as
::std::iter::Step>::steps_between(&Self::index(*start),
&Self::index(*end))
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
#[inline]
fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_add(u);
(Self::from_usize(s), o)
}
#[inline]
fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_sub(u);
(Self::from_usize(s), o)
}
}
impl ::std::cmp::Ord for VariantIdx {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_u32().cmp(&other.as_u32())
}
}
impl ::std::cmp::PartialOrd for VariantIdx {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl ::rustc_data_structures::stable_hash::StableHash for VariantIdx {
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
hcx: &mut __Hcx,
hasher: &mut ::rustc_data_structures::stable_hash::StableHasher) {
self.as_u32().stable_hash(hcx, hasher)
}
}
impl From<VariantIdx> for u32 {
#[inline]
fn from(v: VariantIdx) -> u32 { v.as_u32() }
}
impl From<VariantIdx> for usize {
#[inline]
fn from(v: VariantIdx) -> usize { v.as_usize() }
}
impl From<usize> for VariantIdx {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for VariantIdx {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for VariantIdx {}
impl ::std::cmp::PartialEq for VariantIdx {
fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for VariantIdx { }
impl ::std::hash::Hash for VariantIdx {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for
VariantIdx {
fn decode(d: &mut D) -> Self { Self::from_u32(d.read_u32()) }
}
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for
VariantIdx {
fn encode(&self, e: &mut E) { e.emit_u32(self.as_u32()); }
}
impl ::std::fmt::Debug for VariantIdx {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("{0}", self.as_u32()))
}
}rustc_index::newtype_index! {
65 #[stable_hash]
76 #[encodable]
77 #[orderable]
78 #[gate_rustc_only]
79 pub struct VariantIdx {
80 const FIRST_VARIANT = 0;
82 }
83}
84
85fn absent<'a, FieldIdx, VariantIdx, F>(fields: &IndexSlice<FieldIdx, F>) -> bool
91where
92 FieldIdx: Idx,
93 VariantIdx: Idx,
94 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
95{
96 let uninhabited = fields.iter().any(|f| f.is_uninhabited());
97 let is_1zst = fields.iter().all(|f| f.is_1zst());
100 uninhabited && is_1zst
101}
102
103enum NicheBias {
105 Start,
106 End,
107}
108
109#[derive(#[automatically_derived]impl<F: ::core::marker::Copy> ::core::marker::Copy for
LayoutCalculatorError<F> {
}Copy, #[automatically_derived]impl<F: ::core::clone::Clone> ::core::clone::Clone for
LayoutCalculatorError<F> {
#[inline]
fn clone(&self) -> Self {
match self {
Self::UnexpectedUnsized(__self_0) =>
LayoutCalculatorError::UnexpectedUnsized(::core::clone::Clone::clone(__self_0)),
Self::SizeOverflow => LayoutCalculatorError::SizeOverflow,
Self::EmptyUnion => LayoutCalculatorError::EmptyUnion,
Self::ReprConflict => LayoutCalculatorError::ReprConflict,
Self::ZeroLengthSimdType =>
LayoutCalculatorError::ZeroLengthSimdType,
Self::OversizedSimdType { max_lanes: __self_0 } =>
LayoutCalculatorError::OversizedSimdType {
max_lanes: ::core::clone::Clone::clone(__self_0),
},
Self::NonPrimitiveSimdType(__self_0) =>
LayoutCalculatorError::NonPrimitiveSimdType(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]impl<F: ::core::fmt::Debug> ::core::fmt::Debug for
LayoutCalculatorError<F> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::UnexpectedUnsized(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"UnexpectedUnsized", &__self_0),
Self::SizeOverflow =>
::core::fmt::Formatter::write_str(f, "SizeOverflow"),
Self::EmptyUnion =>
::core::fmt::Formatter::write_str(f, "EmptyUnion"),
Self::ReprConflict =>
::core::fmt::Formatter::write_str(f, "ReprConflict"),
Self::ZeroLengthSimdType =>
::core::fmt::Formatter::write_str(f, "ZeroLengthSimdType"),
Self::OversizedSimdType { max_lanes: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"OversizedSimdType", "max_lanes", &__self_0),
Self::NonPrimitiveSimdType(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"NonPrimitiveSimdType", &__self_0),
}
}
}Debug, #[automatically_derived]impl<F: ::core::cmp::PartialEq>
::core::marker::StructuralPartialEq for LayoutCalculatorError<F> {
}
#[automatically_derived]impl<F: ::core::cmp::PartialEq> ::core::cmp::PartialEq
for LayoutCalculatorError<F> {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::UnexpectedUnsized(__self_0),
Self::UnexpectedUnsized(__arg1_0)) => __self_0 == __arg1_0,
(Self::OversizedSimdType { max_lanes: __self_0 },
Self::OversizedSimdType { max_lanes: __arg1_0 }) =>
__self_0 == __arg1_0,
(Self::NonPrimitiveSimdType(__self_0),
Self::NonPrimitiveSimdType(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]impl<F: ::core::cmp::Eq> ::core::cmp::Eq for
LayoutCalculatorError<F> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<F>;
let _: ::core::cmp::AssertParamIsEq<usize>;
}
}Eq)]
110pub enum LayoutCalculatorError<F> {
111 UnexpectedUnsized(F),
118
119 SizeOverflow,
121
122 EmptyUnion,
124
125 ReprConflict,
127
128 ZeroLengthSimdType,
130
131 OversizedSimdType { max_lanes: usize },
133
134 NonPrimitiveSimdType(F),
136}
137
138impl<F> LayoutCalculatorError<F> {
139 pub fn without_payload(&self) -> LayoutCalculatorError<()> {
140 use LayoutCalculatorError::*;
141 match *self {
142 UnexpectedUnsized(_) => UnexpectedUnsized(()),
143 SizeOverflow => SizeOverflow,
144 EmptyUnion => EmptyUnion,
145 ReprConflict => ReprConflict,
146 ZeroLengthSimdType => ZeroLengthSimdType,
147 OversizedSimdType { max_lanes } => OversizedSimdType { max_lanes },
148 NonPrimitiveSimdType(_) => NonPrimitiveSimdType(()),
149 }
150 }
151
152 pub fn fallback_fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 use LayoutCalculatorError::*;
157 f.write_str(match self {
158 UnexpectedUnsized(_) => "an unsized type was found where a sized type was expected",
159 SizeOverflow => "size overflow",
160 EmptyUnion => "type is a union with no fields",
161 ReprConflict => "type has an invalid repr",
162 ZeroLengthSimdType | OversizedSimdType { .. } | NonPrimitiveSimdType(_) => {
163 "invalid simd type definition"
164 }
165 })
166 }
167}
168
169type LayoutCalculatorResult<FieldIdx, VariantIdx, F> =
170 Result<LayoutData<FieldIdx, VariantIdx>, LayoutCalculatorError<F>>;
171
172#[derive(#[automatically_derived]impl<Cx: ::core::clone::Clone> ::core::clone::Clone
for LayoutCalculator<Cx> {
#[inline]
fn clone(&self) -> Self {
LayoutCalculator { cx: ::core::clone::Clone::clone(&self.cx) }
}
}Clone, #[automatically_derived]impl<Cx: ::core::marker::Copy> ::core::marker::Copy
for LayoutCalculator<Cx> {
}Copy, #[automatically_derived]impl<Cx: ::core::fmt::Debug> ::core::fmt::Debug for
LayoutCalculator<Cx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"LayoutCalculator", "cx", &&self.cx)
}
}Debug)]
173pub struct LayoutCalculator<Cx> {
174 pub cx: Cx,
175}
176
177impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
178 pub fn new(cx: Cx) -> Self {
179 Self { cx }
180 }
181
182 pub fn layout_of_array_like<FieldIdx: Idx, VariantIdx: Idx, F>(
183 &self,
184 element: &LayoutData<FieldIdx, VariantIdx>,
185 count_if_sized: Option<u64>, ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
187 let count = count_if_sized.unwrap_or(0);
188 let size =
189 element.size.checked_mul(count, &self.cx).ok_or(LayoutCalculatorError::SizeOverflow)?;
190
191 Ok(LayoutData {
192 variants: Variants::Single { index: VariantIdx::new(0) },
193 fields: FieldsShape::Array { stride: element.size, count },
194 backend_repr: BackendRepr::Memory { sized: count_if_sized.is_some() },
195 largest_niche: element.largest_niche.filter(|_| count != 0),
196 uninhabited: element.uninhabited && count != 0,
197 align: element.align,
198 size,
199 max_repr_align: None,
200 unadjusted_abi_align: element.align.abi,
201 repr_c: element.repr_c,
202 randomization_seed: element.randomization_seed.wrapping_add(Hash64::new(count)),
203 })
204 }
205
206 pub fn layout_of_scalable_vector_type<FieldIdx, VariantIdx, F>(
207 &self,
208 element: F,
209 count: u64,
210 number_of_vectors: NumScalableVectors,
211 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
212 where
213 FieldIdx: Idx,
214 VariantIdx: Idx,
215 F: AsRef<LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
216 {
217 vector_type_layout(
218 SimdVectorKind::Scalable(number_of_vectors),
219 self.cx.data_layout(),
220 element,
221 count,
222 )
223 }
224
225 pub fn layout_of_simd_type<FieldIdx, VariantIdx, F>(
226 &self,
227 element: F,
228 count: u64,
229 repr_packed: bool,
230 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
231 where
232 FieldIdx: Idx,
233 VariantIdx: Idx,
234 F: AsRef<LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
235 {
236 let kind = if repr_packed { SimdVectorKind::PackedFixed } else { SimdVectorKind::Fixed };
237 vector_type_layout(kind, self.cx.data_layout(), element, count)
238 }
239
240 pub fn layout_of_coroutine<'a, F, VariantIdx, FieldIdx, LocalIdx>(
245 &self,
246 local_layouts: &IndexSlice<LocalIdx, F>,
247 prefix_layouts: IndexVec<FieldIdx, F>,
248 variant_fields: &IndexSlice<VariantIdx, IndexVec<FieldIdx, LocalIdx>>,
249 storage_conflicts: &BitMatrix<LocalIdx, LocalIdx>,
250 tag_to_layout: impl Fn(Scalar) -> F,
251 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
252 where
253 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
254 VariantIdx: Idx,
255 FieldIdx: Idx,
256 LocalIdx: Idx,
257 {
258 coroutine::layout(
259 self,
260 local_layouts,
261 prefix_layouts,
262 variant_fields,
263 storage_conflicts,
264 tag_to_layout,
265 )
266 }
267
268 pub fn layout_of_univariant<'a, FieldIdx, VariantIdx, F>(
274 &self,
275 fields: &IndexSlice<FieldIdx, F>,
276 repr: &ReprOptions,
277 kind: StructKind,
278 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
279 where
280 FieldIdx: Idx,
281 VariantIdx: Idx,
282 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
283 {
284 let dl = self.cx.data_layout();
285 let layout = self.layout_of_univariant_biased(fields, repr, kind, NicheBias::Start);
286 if let Ok(layout) = &layout
292 && !#[allow(non_exhaustive_omitted_patterns)] match kind {
StructKind::MaybeUnsized => true,
_ => false,
}matches!(kind, StructKind::MaybeUnsized)
296 && let Some(niche) = layout.largest_niche
297 && let head_space = niche.offset.bytes()
298 && let niche_len = niche.value.size(dl).bytes()
299 && let tail_space = layout.size.bytes() - head_space - niche_len
300 && (fields.len() > 1 && head_space != 0 && tail_space > 0)
304 {
305 let alt_layout = self
306 .layout_of_univariant_biased(fields, repr, kind, NicheBias::End)
307 .expect("alt layout should always work");
308 let alt_niche = alt_layout
309 .largest_niche
310 .expect("alt layout should have a niche like the regular one");
311 let alt_head_space = alt_niche.offset.bytes();
312 let alt_niche_len = alt_niche.value.size(dl).bytes();
313 let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len;
314
315 if true {
{
match (&layout.size.bytes(), &alt_layout.size.bytes()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());
316
317 let prefer_alt_layout = alt_head_space > head_space && alt_head_space > tail_space;
318
319 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs:319",
"rustc_abi::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(319u32),
::tracing_core::__macro_support::Option::Some("rustc_abi::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("sz: {0}, default_niche_at: {1}+{2}, default_tail_space: {3}, alt_niche_at/head_space: {4}+{5}, alt_tail: {6}, num_fields: {7}, better: {8}\nlayout: {9}\nalt_layout: {10}\n",
layout.size.bytes(), head_space, niche_len, tail_space,
alt_head_space, alt_niche_len, alt_tail_space,
layout.fields.count(), prefer_alt_layout,
self.format_field_niches(layout, fields),
self.format_field_niches(&alt_layout, fields)) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
320 "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
321 layout: {}\n\
322 alt_layout: {}\n",
323 layout.size.bytes(),
324 head_space,
325 niche_len,
326 tail_space,
327 alt_head_space,
328 alt_niche_len,
329 alt_tail_space,
330 layout.fields.count(),
331 prefer_alt_layout,
332 self.format_field_niches(layout, fields),
333 self.format_field_niches(&alt_layout, fields),
334 );
335
336 if prefer_alt_layout {
337 return Ok(alt_layout);
338 }
339 }
340 layout
341 }
342
343 pub fn layout_of_struct_or_enum<'a, FieldIdx, VariantIdx, F>(
344 &self,
345 repr: &ReprOptions,
346 variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
347 is_enum: bool,
348 niche_optimizations: NicheOptimizations,
349 discr_range_of_repr: impl Fn(RangeFrom<i128>, RangeToInclusive<u128>) -> (Integer, bool),
350 discriminants: impl Iterator<Item = (VariantIdx, u128)>,
351 always_sized: bool,
352 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
353 where
354 FieldIdx: Idx,
355 VariantIdx: Idx,
356 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
357 {
358 let (present_first, present_second) = {
359 let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| {
360 if !repr.inhibit_enum_layout_opt() && absent(v) { None } else { Some(i) }
361 });
362 (present_variants.next(), present_variants.next())
363 };
364 let present_first = match present_first {
365 Some(present_first) => present_first,
366 None if is_enum => {
368 return Ok(LayoutData::never_type(&self.cx));
369 }
370 None => VariantIdx::new(0),
373 };
374
375 if !is_enum ||
377 (present_second.is_none() && !repr.inhibit_enum_layout_opt())
379 {
380 self.layout_of_struct(
381 repr,
382 variants,
383 present_first,
384 is_enum,
385 niche_optimizations,
386 always_sized,
387 )
388 } else {
389 if !is_enum { ::core::panicking::panic("assertion failed: is_enum") };assert!(is_enum);
393 self.layout_of_enum(repr, variants, discr_range_of_repr, discriminants)
394 }
395 }
396
397 pub fn layout_of_union<'a, FieldIdx, VariantIdx, F>(
398 &self,
399 repr: &ReprOptions,
400 variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
401 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
402 where
403 FieldIdx: Idx,
404 VariantIdx: Idx,
405 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
406 {
407 let dl = self.cx.data_layout();
408 let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
409 let mut max_repr_align = repr.align;
410
411 struct AbiMismatch;
414 let mut common_non_zst_repr_and_align = if repr.inhibits_union_abi_opt() {
415 Err(AbiMismatch)
417 } else {
418 Ok(None)
419 };
420
421 let mut size = Size::ZERO;
422 let only_variant_idx = VariantIdx::new(0);
423 let only_variant = &variants[only_variant_idx];
424 for field in only_variant {
425 if field.is_unsized() {
426 return Err(LayoutCalculatorError::UnexpectedUnsized(*field));
427 }
428
429 align = align.max(field.align.abi);
430 max_repr_align = max_repr_align.max(field.max_repr_align);
431 size = cmp::max(size, field.size);
432
433 if field.is_zst() {
434 continue;
436 }
437
438 if let Ok(common) = common_non_zst_repr_and_align {
439 let field_abi = field.backend_repr.to_union();
441
442 if let Some((common_abi, common_align)) = common {
443 if common_abi != field_abi {
444 common_non_zst_repr_and_align = Err(AbiMismatch);
446 } else {
447 if !#[allow(non_exhaustive_omitted_patterns)] match common_abi {
BackendRepr::Memory { .. } => true,
_ => false,
}matches!(common_abi, BackendRepr::Memory { .. }) {
450 {
match (&common_align, &field.align.abi) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("non-Aggregate field with matching ABI but differing alignment")));
}
}
}
};assert_eq!(
451 common_align, field.align.abi,
452 "non-Aggregate field with matching ABI but differing alignment"
453 );
454 }
455 }
456 } else {
457 common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi)));
459 }
460 }
461 }
462
463 if let Some(pack) = repr.pack {
464 align = align.min(pack);
465 }
466 let unadjusted_abi_align = align;
469 if let Some(repr_align) = repr.align {
470 align = align.max(repr_align);
471 }
472 let align = align;
474
475 let backend_repr = match common_non_zst_repr_and_align {
478 Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true },
479 Ok(Some((repr, _))) => match repr {
480 BackendRepr::Scalar(_) | BackendRepr::ScalarPair { .. }
482 if repr.scalar_platform_align(dl).unwrap() != align =>
483 {
484 BackendRepr::Memory { sized: true }
485 }
486 BackendRepr::SimdVector { element, count: _ }
488 if element.default_align(dl).abi > align =>
489 {
490 BackendRepr::Memory { sized: true }
491 }
492 BackendRepr::Scalar(..)
494 | BackendRepr::ScalarPair { .. }
495 | BackendRepr::SimdVector { .. }
496 | BackendRepr::SimdScalableVector { .. }
497 | BackendRepr::Memory { .. } => repr,
498 },
499 };
500
501 let Some(union_field_count) = NonZero::new(only_variant.len()) else {
502 return Err(LayoutCalculatorError::EmptyUnion);
503 };
504
505 let repr_c =
507 repr.c() || (repr.transparent() && only_variant.iter().any(|field| field.repr_c));
508
509 let combined_seed = only_variant
510 .iter()
511 .map(|v| v.randomization_seed)
512 .fold(repr.field_shuffle_seed, |acc, seed| acc.wrapping_add(seed));
513
514 Ok(LayoutData {
515 variants: Variants::Single { index: only_variant_idx },
516 fields: FieldsShape::Union(union_field_count),
517 backend_repr,
518 largest_niche: None,
519 uninhabited: false,
520 align: AbiAlign::new(align),
521 size: size.align_to(align),
522 max_repr_align,
523 unadjusted_abi_align,
524 repr_c,
525 randomization_seed: combined_seed,
526 })
527 }
528
529 fn layout_of_struct<'a, FieldIdx, VariantIdx, F>(
534 &self,
535 repr: &ReprOptions,
536 variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
537 variant_idx: VariantIdx,
538 is_enum: bool,
539 niche_optimizations: NicheOptimizations,
540 always_sized: bool,
541 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
542 where
543 FieldIdx: Idx,
544 VariantIdx: Idx,
545 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
546 {
547 let dl = self.cx.data_layout();
548 let v = variant_idx;
549 let kind = if is_enum || variants[v].is_empty() || always_sized {
550 StructKind::AlwaysSized
551 } else {
552 StructKind::MaybeUnsized
553 };
554
555 let mut st = self.layout_of_univariant(&variants[v], repr, kind)?;
556 st.variants = Variants::Single { index: v };
557
558 if niche_optimizations == NicheOptimizations::Disabled {
559 let hide_niches = |scalar: &mut _| match scalar {
560 Scalar::Initialized { value, valid_range } => {
561 *valid_range = WrappingRange::full(value.size(dl))
562 }
563 Scalar::Union { .. } => {}
565 };
566 match &mut st.backend_repr {
567 BackendRepr::Scalar(scalar) => hide_niches(scalar),
568 BackendRepr::ScalarPair { a, b, b_offset: _ } => {
569 hide_niches(a);
570 hide_niches(b);
571 }
572 BackendRepr::SimdVector { element, .. }
573 | BackendRepr::SimdScalableVector { element, .. } => hide_niches(element),
574 BackendRepr::Memory { sized: _ } => {}
575 }
576 st.largest_niche = None;
577 return Ok(st);
578 }
579
580 Ok(st)
581 }
582
583 fn layout_of_enum<'a, FieldIdx, VariantIdx, F>(
584 &self,
585 repr: &ReprOptions,
586 variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
587 discr_range_of_repr: impl Fn(RangeFrom<i128>, RangeToInclusive<u128>) -> (Integer, bool),
588 discriminants: impl Iterator<Item = (VariantIdx, u128)>,
589 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
590 where
591 FieldIdx: Idx,
592 VariantIdx: Idx,
593 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
594 {
595 let dl = self.cx.data_layout();
596 if repr.packed() {
598 return Err(LayoutCalculatorError::ReprConflict);
599 }
600
601 let calculate_niche_filling_layout = || -> Option<LayoutData<FieldIdx, VariantIdx>> {
602 struct VariantLayoutInfo {
603 align_abi: Align,
604 }
605
606 if repr.inhibit_enum_layout_opt() {
607 return None;
608 }
609
610 if variants.len() < 2 {
611 return None;
612 }
613
614 let mut align = dl.aggregate_align;
615 let mut max_repr_align = repr.align;
616 let mut unadjusted_abi_align = align;
617 let mut combined_seed = repr.field_shuffle_seed;
618
619 let mut variants_info = IndexVec::<VariantIdx, _>::with_capacity(variants.len());
620 let mut variant_layouts = variants
621 .iter()
622 .map(|v| {
623 let st = self.layout_of_univariant(v, repr, StructKind::AlwaysSized).ok()?;
624
625 variants_info.push(VariantLayoutInfo { align_abi: st.align.abi });
626
627 align = align.max(st.align.abi);
628 max_repr_align = max_repr_align.max(st.max_repr_align);
629 unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
630 combined_seed = combined_seed.wrapping_add(st.randomization_seed);
631
632 Some(VariantLayout::from_layout(st))
633 })
634 .collect::<Option<IndexVec<VariantIdx, _>>>()?;
635
636 let largest_variant_index = variant_layouts
637 .iter_enumerated()
638 .max_by_key(|(_i, layout)| layout.size.bytes())
639 .map(|(i, _layout)| i)?;
640
641 let all_indices = variants.indices();
642 let needs_disc =
643 |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
644 let niche_variants = RangeInclusive {
645 start: all_indices.clone().find(|v| needs_disc(*v)).unwrap(),
646 last: all_indices.rev().find(|v| needs_disc(*v)).unwrap(),
647 };
648
649 let count =
650 (niche_variants.last.index() as u128 - niche_variants.start.index() as u128) + 1;
651
652 let niche = variant_layouts[largest_variant_index].largest_niche?;
654 let (niche_start, niche_scalar) = niche.reserve(dl, count)?;
655 let niche_offset = niche.offset;
656 let niche_size = niche.value.size(dl);
657 let size = variant_layouts[largest_variant_index].size.align_to(align);
658
659 let all_variants_fit = variant_layouts.iter_enumerated_mut().all(|(i, layout)| {
660 if i == largest_variant_index {
661 return true;
662 }
663
664 layout.largest_niche = None;
665
666 if layout.size <= niche_offset {
667 return true;
669 }
670
671 let this_align = variants_info[i].align_abi;
673 let this_offset = (niche_offset + niche_size).align_to(this_align);
674
675 if this_offset + layout.size > size {
676 return false;
677 }
678
679 for offset in layout.field_offsets.iter_mut() {
681 *offset += this_offset;
682 }
683
684 if !layout.is_uninhabited() {
686 layout.backend_repr = BackendRepr::Memory { sized: true };
687 }
688 layout.size += this_offset;
689
690 true
691 });
692
693 if !all_variants_fit {
694 return None;
695 }
696
697 let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar);
698
699 let others_zst = variant_layouts
700 .iter_enumerated()
701 .all(|(i, layout)| i == largest_variant_index || layout.size == Size::ZERO);
702 let same_size = size == variant_layouts[largest_variant_index].size;
703 let same_align = align == variants_info[largest_variant_index].align_abi;
704
705 let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited());
706 let abi = if same_size && same_align && others_zst {
707 match variant_layouts[largest_variant_index].backend_repr {
708 BackendRepr::Scalar(_) => BackendRepr::Scalar(niche_scalar),
711 BackendRepr::ScalarPair { a: first, b: second, b_offset } => {
712 if niche_offset == Size::ZERO {
715 BackendRepr::ScalarPair {
716 a: niche_scalar,
717 b: second.to_union(),
718 b_offset,
719 }
720 } else {
721 BackendRepr::ScalarPair {
722 a: first.to_union(),
723 b: niche_scalar,
724 b_offset,
725 }
726 }
727 }
728 _ => BackendRepr::Memory { sized: true },
729 }
730 } else {
731 BackendRepr::Memory { sized: true }
732 };
733
734 let layout = LayoutData {
735 variants: Variants::Multiple {
736 tag: niche_scalar,
737 tag_encoding: TagEncoding::Niche {
738 untagged_variant: largest_variant_index,
739 niche_variants,
740 niche_start,
741 },
742 tag_field: FieldIdx::new(0),
743 variants: variant_layouts,
744 },
745 fields: FieldsShape::Arbitrary {
746 offsets: [niche_offset].into(),
747 in_memory_order: [FieldIdx::new(0)].into(),
748 },
749 backend_repr: abi,
750 largest_niche,
751 uninhabited,
752 size,
753 align: AbiAlign::new(align),
754 max_repr_align,
755 unadjusted_abi_align,
756 repr_c: repr.c(),
757 randomization_seed: combined_seed,
758 };
759
760 Some(layout)
761 };
762
763 let niche_filling_layout = calculate_niche_filling_layout();
764
765 let discr_type = repr.discr_type();
766 let discr_size = Integer::from_attr(dl, discr_type).size();
767
768 let necessary_discriminants: Vec<u128> = discriminants
769 .filter(|&(i, _)| repr.c() || variants[i].iter().all(|f| !f.is_uninhabited()))
770 .map(|(_, val)| val)
771 .collect();
772
773 let (min_negative, max_positive): (i128, u128) = if discr_type.is_signed() {
776 necessary_discriminants.iter().copied().map(|val| discr_size.sign_extend(val)).fold(
777 (0_i128, 0_u128),
778 |(min, max), val| {
779 if let Ok(val) = u128::try_from(val) {
780 (min, max.max(val))
781 } else {
782 (min.min(val), max)
783 }
784 },
785 )
786 } else {
787 (0, necessary_discriminants.iter().copied().max().unwrap_or(0))
789 };
790 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs:790",
"rustc_abi::layout", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(790u32),
::tracing_core::__macro_support::Option::Some("rustc_abi::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("min_negative")
}> =
::tracing::__macro_support::FieldName::new("min_negative");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("max_positive")
}> =
::tracing::__macro_support::FieldName::new("max_positive");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&min_negative)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&max_positive)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!(?min_negative, ?max_positive);
791
792 let (min_ity, signed) = discr_range_of_repr(
793 RangeFrom { start: min_negative },
794 RangeToInclusive { last: max_positive },
795 ); let mut align = dl.aggregate_align;
798 let mut max_repr_align = repr.align;
799 let mut unadjusted_abi_align = align;
800 let mut combined_seed = repr.field_shuffle_seed;
801
802 let mut size = Size::ZERO;
803
804 let mut start_align = Align::from_bytes(256).unwrap();
806 {
match (&Integer::for_align(dl, start_align), &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(Integer::for_align(dl, start_align), None);
807
808 let mut prefix_align = min_ity.align(dl).abi;
814 if repr.c() {
815 for fields in variants {
816 for field in fields {
817 prefix_align = prefix_align.max(field.align.abi);
818 }
819 }
820 }
821
822 let mut layout_variants = variants
824 .iter()
825 .map(|field_layouts| {
826 let st = self.layout_of_univariant(
827 field_layouts,
828 repr,
829 StructKind::Prefixed(min_ity.size(), prefix_align),
830 )?;
831 for field_idx in st.fields.index_by_increasing_offset() {
834 let field = &field_layouts[FieldIdx::new(field_idx)];
835 if !field.is_1zst() {
836 start_align = start_align.min(field.align.abi);
837 break;
838 }
839 }
840 size = cmp::max(size, st.size);
841 align = align.max(st.align.abi);
842 max_repr_align = max_repr_align.max(st.max_repr_align);
843 unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
844 combined_seed = combined_seed.wrapping_add(st.randomization_seed);
845 Ok(VariantLayout::from_layout(st))
846 })
847 .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
848
849 size = size.align_to(align);
851
852 if size.bytes() >= dl.obj_size_bound() {
854 return Err(LayoutCalculatorError::SizeOverflow);
855 }
856
857 let typeck_ity = Integer::from_attr(dl, repr.discr_type());
858 if typeck_ity < min_ity {
859 {
::core::panicking::panic_fmt(format_args!("layout decided on a larger discriminant type ({0:?}) than typeck ({1:?})",
min_ity, typeck_ity));
};panic!(
869 "layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?})"
870 );
871 }
874
875 let mut ity = if repr.c() || repr.int.is_some() {
886 min_ity
887 } else {
888 Integer::for_align(dl, start_align).unwrap_or(min_ity)
889 };
890
891 if ity <= min_ity {
894 ity = min_ity;
895 } else {
896 let old_ity_size = min_ity.size();
898 let new_ity_size = ity.size();
899 for variant in &mut layout_variants {
900 for i in &mut variant.field_offsets {
901 if *i <= old_ity_size {
902 {
match (&*i, &old_ity_size) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(*i, old_ity_size);
903 *i = new_ity_size;
904 }
905 }
906 if variant.size <= old_ity_size {
908 variant.size = new_ity_size;
909 }
910 }
911 }
912
913 let tag_valid_range = {
914 let tag_size = ity.size();
915 let tags = necessary_discriminants.into_iter().map(|d| tag_size.truncate(d));
916 WrappingRange::smallest_range_containing(tags, tag_size)
917 .unwrap_or(WrappingRange { start: 0, end: 0 })
919 };
920 let tag = Scalar::Initialized {
921 value: Primitive::Int(ity, signed),
922 valid_range: tag_valid_range,
923 };
924 let mut abi = BackendRepr::Memory { sized: true };
925
926 let uninhabited = layout_variants.iter().all(|v| v.is_uninhabited());
927 if tag.size(dl) == size {
928 abi = BackendRepr::Scalar(tag);
931 } else {
932 let mut common_prim = None;
935 let mut common_prim_initialized_in_all_variants = true;
936 for (field_layouts, layout_variant) in iter::zip(variants, &layout_variants) {
937 let mut fields = iter::zip(field_layouts, &layout_variant.field_offsets)
940 .filter(|p| !p.0.is_zst());
941 let (field, offset) = match (fields.next(), fields.next()) {
942 (None, None) => {
943 common_prim_initialized_in_all_variants = false;
944 continue;
945 }
946 (Some(pair), None) => pair,
947 _ => {
948 common_prim = None;
949 break;
950 }
951 };
952 let prim = match field.backend_repr {
953 BackendRepr::Scalar(scalar) => {
954 common_prim_initialized_in_all_variants &=
955 #[allow(non_exhaustive_omitted_patterns)] match scalar {
Scalar::Initialized { .. } => true,
_ => false,
}matches!(scalar, Scalar::Initialized { .. });
956 scalar.primitive()
957 }
958 _ => {
959 common_prim = None;
960 break;
961 }
962 };
963 if let Some((old_prim, common_offset)) = common_prim {
964 if offset != common_offset {
966 common_prim = None;
967 break;
968 }
969 let new_prim = match (old_prim, prim) {
973 (x, y) if x == y => x,
975 (p @ Primitive::Int(x, _), Primitive::Int(y, _)) if x == y => p,
978 (p @ Primitive::Pointer(_), i @ Primitive::Int(..))
982 | (i @ Primitive::Int(..), p @ Primitive::Pointer(_))
983 if p.size(dl) == i.size(dl)
984 && p.default_align(dl) == i.default_align(dl) =>
985 {
986 p
987 }
988 _ => {
989 common_prim = None;
990 break;
991 }
992 };
993 common_prim = Some((new_prim, common_offset));
995 } else {
996 common_prim = Some((prim, offset));
997 }
998 }
999 if let Some((prim, offset)) = common_prim {
1000 let prim_scalar = if common_prim_initialized_in_all_variants {
1001 let size = prim.size(dl);
1002 if !(size.bits() <= 128) {
::core::panicking::panic("assertion failed: size.bits() <= 128")
};assert!(size.bits() <= 128);
1003 Scalar::Initialized { value: prim, valid_range: WrappingRange::full(size) }
1004 } else {
1005 Scalar::Union { value: prim }
1007 };
1008 let pair =
1009 LayoutData::<FieldIdx, VariantIdx>::scalar_pair(&self.cx, tag, prim_scalar);
1010 let pair_offsets = match pair.fields {
1011 FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
1012 {
match (&in_memory_order.raw, &[FieldIdx::new(0), FieldIdx::new(1)]) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(in_memory_order.raw, [FieldIdx::new(0), FieldIdx::new(1)]);
1013 offsets
1014 }
1015 _ => {
::core::panicking::panic_fmt(format_args!("encountered a non-arbitrary layout during enum layout"));
}panic!("encountered a non-arbitrary layout during enum layout"),
1016 };
1017 if pair_offsets[FieldIdx::new(0)] == Size::ZERO
1018 && pair_offsets[FieldIdx::new(1)] == *offset
1019 && align == pair.align.abi
1020 && size == pair.size
1021 {
1022 abi = pair.backend_repr;
1025 }
1026 }
1027 }
1028
1029 if #[allow(non_exhaustive_omitted_patterns)] match abi {
BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. } => true,
_ => false,
}matches!(abi, BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. }) {
1033 for variant in &mut layout_variants {
1034 if #[allow(non_exhaustive_omitted_patterns)] match variant.backend_repr {
BackendRepr::Memory { .. } if variant.has_fields() => true,
_ => false,
}matches!(variant.backend_repr, BackendRepr::Memory { .. } if variant.has_fields())
1037 {
1038 variant.backend_repr = abi;
1039 variant.size = cmp::max(variant.size, size);
1041 }
1042 }
1043 }
1044
1045 let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
1046
1047 let tagged_layout = LayoutData {
1048 variants: Variants::Multiple {
1049 tag,
1050 tag_encoding: TagEncoding::Direct,
1051 tag_field: FieldIdx::new(0),
1052 variants: layout_variants,
1053 },
1054 fields: FieldsShape::Arbitrary {
1055 offsets: [Size::ZERO].into(),
1056 in_memory_order: [FieldIdx::new(0)].into(),
1057 },
1058 largest_niche,
1059 uninhabited,
1060 backend_repr: abi,
1061 align: AbiAlign::new(align),
1062 size,
1063 max_repr_align,
1064 unadjusted_abi_align,
1065 repr_c: repr.c(),
1066 randomization_seed: combined_seed,
1067 };
1068
1069 let best_layout = match (tagged_layout, niche_filling_layout) {
1070 (tl, Some(nl)) => {
1071 use cmp::Ordering::*;
1075 let niche_size = |l: &LayoutData<FieldIdx, VariantIdx>| {
1076 l.largest_niche.map_or(0, |n| n.available(dl))
1077 };
1078 match (tl.size.cmp(&nl.size), niche_size(&tl).cmp(&niche_size(&nl))) {
1079 (Greater, _) => nl,
1080 (Equal, Less) => nl,
1081 _ => tl,
1082 }
1083 }
1084 (tl, None) => tl,
1085 };
1086
1087 Ok(best_layout)
1088 }
1089
1090 fn layout_of_univariant_biased<'a, FieldIdx, VariantIdx, F>(
1091 &self,
1092 fields: &IndexSlice<FieldIdx, F>,
1093 repr: &ReprOptions,
1094 kind: StructKind,
1095 niche_bias: NicheBias,
1096 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
1097 where
1098 FieldIdx: Idx,
1099 VariantIdx: Idx,
1100 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
1101 {
1102 let dl = self.cx.data_layout();
1103 let pack = repr.pack;
1104 let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
1105 let mut max_repr_align = repr.align;
1106 let mut in_memory_order: IndexVec<u32, FieldIdx> = fields.indices().collect();
1107 let optimize_field_order = !repr.inhibit_struct_field_reordering();
1108 let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
1109 let optimizing = &mut in_memory_order.raw[..end];
1110 let fields_excluding_tail = &fields.raw[..end];
1111 let field_seed = fields_excluding_tail
1113 .iter()
1114 .fold(Hash64::ZERO, |acc, f| acc.wrapping_add(f.randomization_seed));
1115
1116 if optimize_field_order && fields.len() > 1 {
1117 if repr.can_randomize_type_layout() && truecfg!(feature = "randomize") {
1126 #[cfg(feature = "randomize")]
1127 {
1128 use rand::SeedableRng;
1129 use rand::seq::SliceRandom;
1130 let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64(
1133 field_seed.wrapping_add(repr.field_shuffle_seed).as_u64(),
1134 );
1135
1136 optimizing.shuffle(&mut rng);
1138 }
1139 } else {
1141 let max_field_align =
1144 fields_excluding_tail.iter().map(|f| f.align.bytes()).max().unwrap_or(1);
1145 let largest_niche_size = fields_excluding_tail
1146 .iter()
1147 .filter_map(|f| f.largest_niche)
1148 .map(|n| n.available(dl))
1149 .max()
1150 .unwrap_or(0);
1151
1152 let alignment_group_key = |layout: &F| {
1155 if let Some(pack) = pack {
1159 layout.align.abi.min(pack).bytes()
1161 } else {
1162 let align = layout.align.bytes();
1165 let size = layout.size.bytes();
1166 let niche_size = layout.largest_niche.map(|n| n.available(dl)).unwrap_or(0);
1167 let size_as_align = align.max(size).trailing_zeros();
1169 let size_as_align = if largest_niche_size > 0 {
1170 match niche_bias {
1171 NicheBias::Start => {
1175 max_field_align.trailing_zeros().min(size_as_align)
1176 }
1177 NicheBias::End if niche_size == largest_niche_size => {
1181 align.trailing_zeros()
1182 }
1183 NicheBias::End => size_as_align,
1184 }
1185 } else {
1186 size_as_align
1187 };
1188 size_as_align as u64
1189 }
1190 };
1191
1192 match kind {
1193 StructKind::AlwaysSized | StructKind::MaybeUnsized => {
1194 optimizing.sort_by_key(|&x| {
1203 let f = &fields[x];
1204 let field_size = f.size.bytes();
1205 let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
1206 let niche_size_key = match niche_bias {
1207 NicheBias::Start => !niche_size,
1209 NicheBias::End => niche_size,
1211 };
1212 let inner_niche_offset_key = match niche_bias {
1213 NicheBias::Start => f.largest_niche.map_or(0, |n| n.offset.bytes()),
1214 NicheBias::End => f.largest_niche.map_or(0, |n| {
1215 !(field_size - n.value.size(dl).bytes() - n.offset.bytes())
1216 }),
1217 };
1218
1219 (
1220 cmp::Reverse(alignment_group_key(f)),
1222 niche_size_key,
1225 inner_niche_offset_key,
1228 )
1229 });
1230 }
1231
1232 StructKind::Prefixed(..) => {
1233 optimizing.sort_by_key(|&x| {
1238 let f = &fields[x];
1239 let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
1240 (alignment_group_key(f), niche_size)
1241 });
1242 }
1243 }
1244
1245 }
1248 }
1249 let mut unsized_field = None::<&F>;
1254 let mut offsets = IndexVec::from_elem(Size::ZERO, fields);
1255 let mut offset = Size::ZERO;
1256 let mut largest_niche = None;
1257 let mut largest_niche_available = 0;
1258 if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
1259 let prefix_align =
1260 if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
1261 align = align.max(prefix_align);
1262 offset = prefix_size.align_to(prefix_align);
1263 }
1264 for &i in &in_memory_order {
1265 let field = &fields[i];
1266 if let Some(unsized_field) = unsized_field {
1267 return Err(LayoutCalculatorError::UnexpectedUnsized(*unsized_field));
1268 }
1269
1270 if field.is_unsized() {
1271 if let StructKind::MaybeUnsized = kind {
1272 unsized_field = Some(field);
1273 } else {
1274 return Err(LayoutCalculatorError::UnexpectedUnsized(*field));
1275 }
1276 }
1277
1278 let field_align = if let Some(pack) = pack {
1280 field.align.min(AbiAlign::new(pack))
1281 } else {
1282 field.align
1283 };
1284 offset = offset.align_to(field_align.abi);
1285 align = align.max(field_align.abi);
1286 max_repr_align = max_repr_align.max(field.max_repr_align);
1287
1288 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs:1288",
"rustc_abi::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(1288u32),
::tracing_core::__macro_support::Option::Some("rustc_abi::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("univariant offset: {0:?} field: {1:#?}",
offset, field) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("univariant offset: {:?} field: {:#?}", offset, field);
1289 offsets[i] = offset;
1290
1291 if let Some(mut niche) = field.largest_niche {
1292 let available = niche.available(dl);
1293 let prefer_new_niche = match niche_bias {
1295 NicheBias::Start => available > largest_niche_available,
1296 NicheBias::End => available >= largest_niche_available,
1298 };
1299 if prefer_new_niche {
1300 largest_niche_available = available;
1301 niche.offset += offset;
1302 largest_niche = Some(niche);
1303 }
1304 }
1305
1306 offset =
1307 offset.checked_add(field.size, dl).ok_or(LayoutCalculatorError::SizeOverflow)?;
1308 }
1309
1310 let unadjusted_abi_align = align;
1313 if let Some(repr_align) = repr.align {
1314 align = align.max(repr_align);
1315 }
1316 let align = align;
1318
1319 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs:1319",
"rustc_abi::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/92ffebeceaa0a071066f233873c2438e73d70fe7/compiler/rustc_abi/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(1319u32),
::tracing_core::__macro_support::Option::Some("rustc_abi::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("univariant min_size: {0:?}",
offset) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("univariant min_size: {:?}", offset);
1320 let min_size = offset;
1321 let size = min_size.align_to(align);
1322 if size.bytes() >= dl.obj_size_bound() {
1324 return Err(LayoutCalculatorError::SizeOverflow);
1325 }
1326 let mut layout_of_single_non_zst_field = None;
1327 let sized = unsized_field.is_none();
1328 let mut abi = BackendRepr::Memory { sized };
1329
1330 let optimize_abi = !repr.inhibit_newtype_abi_optimization();
1331
1332 if sized && size.bytes() > 0 {
1334 let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.is_zst());
1337
1338 match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
1339 (Some((i, field)), None, None) => {
1341 layout_of_single_non_zst_field = Some(field);
1342
1343 if offsets[i].bytes() == 0 && align == field.align.abi && size == field.size {
1345 match field.backend_repr {
1346 BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. }
1349 if optimize_abi =>
1350 {
1351 abi = field.backend_repr;
1352 }
1353 BackendRepr::ScalarPair { .. } => {
1356 abi = field.backend_repr;
1357 }
1358 _ => {}
1359 }
1360 }
1361 }
1362
1363 (Some((i, a)), Some((j, b)), None) => {
1365 match (a.backend_repr, b.backend_repr) {
1366 (BackendRepr::Scalar(a), BackendRepr::Scalar(b)) => {
1367 let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
1369 ((i, a), (j, b))
1370 } else {
1371 ((j, b), (i, a))
1372 };
1373 let pair =
1374 LayoutData::<FieldIdx, VariantIdx>::scalar_pair(&self.cx, a, b);
1375 let pair_offsets = match pair.fields {
1376 FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
1377 {
match (&in_memory_order.raw, &[FieldIdx::new(0), FieldIdx::new(1)]) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(
1378 in_memory_order.raw,
1379 [FieldIdx::new(0), FieldIdx::new(1)]
1380 );
1381 offsets
1382 }
1383 FieldsShape::Primitive
1384 | FieldsShape::Array { .. }
1385 | FieldsShape::Union(..) => {
1386 {
::core::panicking::panic_fmt(format_args!("encountered a non-arbitrary layout during enum layout"));
}panic!("encountered a non-arbitrary layout during enum layout")
1387 }
1388 };
1389 if offsets[i] == pair_offsets[FieldIdx::new(0)]
1390 && offsets[j] == pair_offsets[FieldIdx::new(1)]
1391 && align == pair.align.abi
1392 && size == pair.size
1393 {
1394 abi = pair.backend_repr;
1397 }
1398 }
1399 _ => {}
1400 }
1401 }
1402
1403 _ => {}
1404 }
1405 }
1406 let uninhabited = fields.iter().any(|f| f.is_uninhabited());
1407
1408 let unadjusted_abi_align = if repr.transparent() {
1409 match layout_of_single_non_zst_field {
1410 Some(l) => l.unadjusted_abi_align,
1411 None => {
1412 align
1414 }
1415 }
1416 } else {
1417 unadjusted_abi_align
1418 };
1419
1420 let repr_c = repr.c() || (repr.transparent() && fields.iter().any(|field| field.repr_c));
1422
1423 let seed = field_seed.wrapping_add(repr.field_shuffle_seed);
1424
1425 Ok(LayoutData {
1426 variants: Variants::Single { index: VariantIdx::new(0) },
1427 fields: FieldsShape::Arbitrary { offsets, in_memory_order },
1428 backend_repr: abi,
1429 largest_niche,
1430 uninhabited,
1431 align: AbiAlign::new(align),
1432 size,
1433 max_repr_align,
1434 unadjusted_abi_align,
1435 repr_c,
1436 randomization_seed: seed,
1437 })
1438 }
1439
1440 fn format_field_niches<'a, FieldIdx, VariantIdx, F>(
1441 &self,
1442 layout: &LayoutData<FieldIdx, VariantIdx>,
1443 fields: &IndexSlice<FieldIdx, F>,
1444 ) -> String
1445 where
1446 FieldIdx: Idx,
1447 VariantIdx: Idx,
1448 F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
1449 {
1450 let dl = self.cx.data_layout();
1451 let mut s = String::new();
1452 for i in layout.fields.index_by_increasing_offset() {
1453 let offset = layout.fields.offset(i);
1454 let f = &fields[FieldIdx::new(i)];
1455 s.write_fmt(format_args!("[o{0}a{1}s{2}", offset.bytes(), f.align.bytes(),
f.size.bytes()))write!(s, "[o{}a{}s{}", offset.bytes(), f.align.bytes(), f.size.bytes()).unwrap();
1456 if let Some(n) = f.largest_niche {
1457 s.write_fmt(format_args!(" n{0}b{1}s{2}", n.offset.bytes(),
n.available(dl).ilog2(), n.value.size(dl).bytes()))write!(
1458 s,
1459 " n{}b{}s{}",
1460 n.offset.bytes(),
1461 n.available(dl).ilog2(),
1462 n.value.size(dl).bytes()
1463 )
1464 .unwrap();
1465 }
1466 s.write_fmt(format_args!("] "))write!(s, "] ").unwrap();
1467 }
1468 s
1469 }
1470}
1471
1472enum SimdVectorKind {
1473 Scalable(NumScalableVectors),
1475 PackedFixed,
1477 Fixed,
1479}
1480
1481fn vector_type_layout<FieldIdx, VariantIdx, F>(
1482 kind: SimdVectorKind,
1483 dl: &TargetDataLayout,
1484 element: F,
1485 count: u64,
1486) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
1487where
1488 FieldIdx: Idx,
1489 VariantIdx: Idx,
1490 F: AsRef<LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
1491{
1492 let elt = element.as_ref();
1493 let count = BackendLaneCount::new(count)?;
1494
1495 let BackendRepr::Scalar(element) = elt.backend_repr else {
1496 return Err(LayoutCalculatorError::NonPrimitiveSimdType(element));
1497 };
1498
1499 let size =
1501 elt.size.checked_mul(count.as_u64(), dl).ok_or(LayoutCalculatorError::SizeOverflow)?;
1502 let (repr, size, align) = match kind {
1503 SimdVectorKind::Scalable(number_of_vectors) => (
1504 BackendRepr::SimdScalableVector { element, count, number_of_vectors },
1505 size.checked_mul(number_of_vectors.0 as u64, dl)
1506 .ok_or(LayoutCalculatorError::SizeOverflow)?,
1507 dl.rust_vector_align(size),
1508 ),
1509 SimdVectorKind::PackedFixed if !count.is_power_of_two() => {
1513 (BackendRepr::Memory { sized: true }, size, Align::max_aligned_factor(size))
1514 }
1515 SimdVectorKind::PackedFixed | SimdVectorKind::Fixed => {
1516 (BackendRepr::SimdVector { element, count }, size, dl.rust_vector_align(size))
1517 }
1518 };
1519 let size = size.align_to(align);
1520
1521 Ok(LayoutData {
1522 variants: Variants::Single { index: VariantIdx::new(0) },
1523 fields: FieldsShape::Arbitrary {
1524 offsets: [Size::ZERO].into(),
1525 in_memory_order: [FieldIdx::new(0)].into(),
1526 },
1527 backend_repr: repr,
1528 largest_niche: elt.largest_niche,
1529 uninhabited: false,
1530 size,
1531 align: AbiAlign::new(align),
1532 max_repr_align: None,
1533 unadjusted_abi_align: elt.align.abi,
1534 repr_c: false,
1535 randomization_seed: elt.randomization_seed.wrapping_add(Hash64::new(count.as_u64())),
1536 })
1537}