1use std::fmt;
2use std::ops::{Deref, Range};
3
4use rustc_data_structures::intern::Interned;
5use rustc_data_structures::range_set::RangeSet;
6use rustc_macros::StableHash;
7
8use crate::layout::{FieldIdx, VariantIdx};
9use crate::{
10 AbiAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche, Numeric,
11 PointeeInfo, Primitive, Size, Variants,
12};
13
14#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for Layout<'a> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'a> ::core::clone::TrivialClone for Layout<'a> { }
#[automatically_derived]
impl<'a> ::core::clone::Clone for Layout<'a> {
#[inline]
fn clone(&self) -> Layout<'a> {
let _:
::core::clone::AssertParamIsClone<Interned<'a,
LayoutData<FieldIdx, VariantIdx>>>;
*self
}
}Clone, #[automatically_derived]
impl<'a> ::core::marker::StructuralPartialEq for Layout<'a> { }
#[automatically_derived]
impl<'a> ::core::cmp::PartialEq for Layout<'a> {
#[inline]
fn eq(&self, other: &Layout<'a>) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl<'a> ::core::cmp::Eq for Layout<'a> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _:
::core::cmp::AssertParamIsEq<Interned<'a,
LayoutData<FieldIdx, VariantIdx>>>;
}
}Eq, #[automatically_derived]
impl<'a> ::core::hash::Hash for Layout<'a> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, const _: () =
{
impl<'a> ::rustc_data_structures::stable_hash::StableHash for
Layout<'a> {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self {
Layout(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
17#[rustc_pass_by_value]
18pub struct Layout<'a>(pub Interned<'a, LayoutData<FieldIdx, VariantIdx>>);
19
20impl<'a> fmt::Debug for Layout<'a> {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 self.0.0.fmt(f)
24 }
25}
26
27impl<'a> Deref for Layout<'a> {
28 type Target = &'a LayoutData<FieldIdx, VariantIdx>;
29 fn deref(&self) -> &&'a LayoutData<FieldIdx, VariantIdx> {
30 &self.0.0
31 }
32}
33
34impl<'a> Layout<'a> {
35 pub fn fields(self) -> &'a FieldsShape<FieldIdx> {
36 &self.0.0.fields
37 }
38
39 pub fn variants(self) -> &'a Variants<FieldIdx, VariantIdx> {
40 &self.0.0.variants
41 }
42
43 pub fn backend_repr(self) -> BackendRepr {
44 self.0.0.backend_repr
45 }
46
47 pub fn largest_niche(self) -> Option<Niche> {
48 self.0.0.largest_niche
49 }
50
51 pub fn align(self) -> AbiAlign {
52 self.0.0.align
53 }
54
55 pub fn size(self) -> Size {
56 self.0.0.size
57 }
58
59 pub fn max_repr_align(self) -> Option<Align> {
60 self.0.0.max_repr_align
61 }
62
63 pub fn unadjusted_abi_align(self) -> Align {
64 self.0.0.unadjusted_abi_align
65 }
66}
67
68#[derive(#[automatically_derived]
impl<'a, Ty: ::core::marker::Copy> ::core::marker::Copy for
TyAndLayout<'a, Ty> {
}Copy, #[automatically_derived]
impl<'a, Ty: ::core::clone::Clone> ::core::clone::Clone for
TyAndLayout<'a, Ty> {
#[inline]
fn clone(&self) -> TyAndLayout<'a, Ty> {
TyAndLayout {
ty: ::core::clone::Clone::clone(&self.ty),
layout: ::core::clone::Clone::clone(&self.layout),
}
}
}Clone, #[automatically_derived]
impl<'a, Ty: ::core::cmp::PartialEq> ::core::marker::StructuralPartialEq for
TyAndLayout<'a, Ty> {
}
#[automatically_derived]
impl<'a, Ty: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
TyAndLayout<'a, Ty> {
#[inline]
fn eq(&self, other: &TyAndLayout<'a, Ty>) -> bool {
self.ty == other.ty && self.layout == other.layout
}
}PartialEq, #[automatically_derived]
impl<'a, Ty: ::core::cmp::Eq> ::core::cmp::Eq for TyAndLayout<'a, Ty> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ty>;
let _: ::core::cmp::AssertParamIsEq<Layout<'a>>;
}
}Eq, #[automatically_derived]
impl<'a, Ty: ::core::hash::Hash> ::core::hash::Hash for TyAndLayout<'a, Ty> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.ty, state);
::core::hash::Hash::hash(&self.layout, state)
}
}Hash, const _: () =
{
impl<'a, Ty> ::rustc_data_structures::stable_hash::StableHash for
TyAndLayout<'a, Ty> where
Ty: ::rustc_data_structures::stable_hash::StableHash {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self {
TyAndLayout { ty: ref __binding_0, layout: ref __binding_1 }
=> {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
76pub struct TyAndLayout<'a, Ty> {
77 pub ty: Ty,
78 pub layout: Layout<'a>,
79}
80
81impl<'a, Ty: fmt::Display> fmt::Debug for TyAndLayout<'a, Ty> {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 f.debug_struct("TyAndLayout")
85 .field("ty", &format_args!("{0}", self.ty)format_args!("{}", self.ty))
86 .field("layout", &self.layout)
87 .finish()
88 }
89}
90
91impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
92 type Target = &'a LayoutData<FieldIdx, VariantIdx>;
93 fn deref(&self) -> &&'a LayoutData<FieldIdx, VariantIdx> {
94 &self.layout.0.0
95 }
96}
97
98impl<'a, Ty> AsRef<LayoutData<FieldIdx, VariantIdx>> for TyAndLayout<'a, Ty> {
99 fn as_ref(&self) -> &LayoutData<FieldIdx, VariantIdx> {
100 &*self.layout.0.0
101 }
102}
103
104pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug + std::fmt::Display {
107 fn ty_and_layout_for_variant(
108 this: TyAndLayout<'a, Self>,
109 cx: &C,
110 variant_index: VariantIdx,
111 ) -> TyAndLayout<'a, Self>;
112 fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>;
113 fn ty_and_layout_pointee_info_at(
114 this: TyAndLayout<'a, Self>,
115 cx: &C,
116 offset: Size,
117 ) -> Option<PointeeInfo>;
118 fn is_adt(this: TyAndLayout<'a, Self>) -> bool;
119 fn is_enum(this: TyAndLayout<'a, Self>) -> bool;
120 fn is_never(this: TyAndLayout<'a, Self>) -> bool;
121 fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
122 fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
123 fn is_transparent(this: TyAndLayout<'a, Self>) -> bool;
124 fn is_complex_number_lang_item(this: TyAndLayout<'a, Self>, cx: &C) -> bool;
125 fn is_scalable_vector(this: TyAndLayout<'a, Self>) -> bool;
126 fn is_pass_indirectly_in_non_rustic_abis_flag_set(this: TyAndLayout<'a, Self>) -> bool;
128}
129
130impl<'a, Ty> TyAndLayout<'a, Ty> {
131 pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
139 where
140 Ty: TyAbiInterface<'a, C>,
141 {
142 Ty::ty_and_layout_for_variant(self, cx, variant_index)
143 }
144
145 pub fn field<C>(self, cx: &C, i: usize) -> Self
146 where
147 Ty: TyAbiInterface<'a, C>,
148 {
149 Ty::ty_and_layout_field(self, cx, i)
150 }
151
152 pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
153 where
154 Ty: TyAbiInterface<'a, C>,
155 {
156 Ty::ty_and_layout_pointee_info_at(self, cx, offset)
157 }
158
159 pub fn is_single_fp_element<C>(self, cx: &C) -> bool
160 where
161 Ty: TyAbiInterface<'a, C>,
162 C: HasDataLayout,
163 {
164 match self.backend_repr {
165 BackendRepr::Scalar(scalar) => {
166 #[allow(non_exhaustive_omitted_patterns)] match scalar.primitive() {
Primitive::Float(Float::F32 | Float::F64) => true,
_ => false,
}matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64))
167 }
168 BackendRepr::Memory { .. } => {
169 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
170 self.field(cx, 0).is_single_fp_element(cx)
171 } else {
172 false
173 }
174 }
175 _ => false,
176 }
177 }
178
179 pub fn is_single_vector_element<C>(self, cx: &C, expected_size: Size) -> bool
180 where
181 Ty: TyAbiInterface<'a, C>,
182 C: HasDataLayout,
183 {
184 match self.backend_repr {
185 BackendRepr::SimdVector { .. } => self.size == expected_size,
186 BackendRepr::Memory { .. } => {
187 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
188 self.field(cx, 0).is_single_vector_element(cx, expected_size)
189 } else {
190 false
191 }
192 }
193 _ => false,
194 }
195 }
196
197 pub fn is_adt<C>(self) -> bool
198 where
199 Ty: TyAbiInterface<'a, C>,
200 {
201 Ty::is_adt(self)
202 }
203
204 pub fn is_enum<C>(self) -> bool
205 where
206 Ty: TyAbiInterface<'a, C>,
207 {
208 Ty::is_enum(self)
209 }
210
211 pub fn is_never<C>(self) -> bool
212 where
213 Ty: TyAbiInterface<'a, C>,
214 {
215 Ty::is_never(self)
216 }
217
218 pub fn is_tuple<C>(self) -> bool
219 where
220 Ty: TyAbiInterface<'a, C>,
221 {
222 Ty::is_tuple(self)
223 }
224
225 pub fn is_unit<C>(self) -> bool
226 where
227 Ty: TyAbiInterface<'a, C>,
228 {
229 Ty::is_unit(self)
230 }
231
232 pub fn is_transparent<C>(self) -> bool
233 where
234 Ty: TyAbiInterface<'a, C>,
235 {
236 Ty::is_transparent(self)
237 }
238
239 pub fn is_complex_number<C>(self, cx: &C) -> bool
242 where
243 Ty: TyAbiInterface<'a, C> + Copy,
244 {
245 self.complex_number(cx).is_some()
246 }
247
248 pub fn is_scalable_vector<C>(self) -> bool
249 where
250 Ty: TyAbiInterface<'a, C>,
251 {
252 Ty::is_scalable_vector(self)
253 }
254
255 pub fn pass_indirectly_in_non_rustic_abis<C>(self, cx: &C) -> bool
267 where
268 Ty: TyAbiInterface<'a, C> + Copy,
269 {
270 let base = self.peel_transparent_wrappers(cx);
271 Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base)
272 }
273
274 pub fn peel_transparent_wrappers<C>(mut self, cx: &C) -> Self
279 where
280 Ty: TyAbiInterface<'a, C> + Copy,
281 {
282 while self.is_transparent()
283 && let Some((_, field)) = self.non_1zst_field(cx)
284 {
285 self = field;
286 }
287
288 self
289 }
290
291 pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(FieldIdx, Self)>
294 where
295 Ty: TyAbiInterface<'a, C> + Copy,
296 {
297 let mut found = None;
298 for field_idx in 0..self.fields.count() {
299 let field = self.field(cx, field_idx);
300 if field.is_1zst() {
301 continue;
302 }
303 if found.is_some() {
304 return None;
306 }
307 found = Some((FieldIdx::from_usize(field_idx), field));
308 }
309 found
310 }
311
312 pub fn complex_number<C>(&self, cx: &C) -> Option<Numeric>
318 where
319 Ty: TyAbiInterface<'a, C> + Copy,
320 {
321 let complex = self.peel_transparent_wrappers(cx);
322 if !Ty::is_complex_number_lang_item(complex, cx) {
323 return None;
324 }
325
326 let component = complex.field(cx, 0).peel_transparent_wrappers(cx);
327
328 let BackendRepr::Scalar(scalar) = component.backend_repr else {
329 return None;
330 };
331
332 let primitive = scalar.primitive();
337 match primitive {
338 Primitive::Int(integer, is_signed) => Some(Numeric::Int(integer, is_signed)),
339 Primitive::Float(float @ (Float::F16 | Float::F32 | Float::F64 | Float::F128)) => {
340 Some(Numeric::Float(float))
341 }
342 Primitive::Pointer(..) => None,
343 }
344 }
345
346 pub fn complex_float<C>(&self, cx: &C) -> Option<Float>
349 where
350 Ty: TyAbiInterface<'a, C> + Copy,
351 {
352 match self.complex_number(cx) {
353 Some(Numeric::Float(float)) => Some(float),
354 _ => None,
355 }
356 }
357
358 pub fn has_variant_dependent_padding<C>(&self, cx: &C) -> bool
361 where
362 Ty: TyAbiInterface<'a, C> + Copy,
363 {
364 match self.variants {
365 Variants::Multiple { .. } => true,
366 Variants::Empty => false,
367 Variants::Single { .. } => match &self.fields {
368 FieldsShape::Primitive | FieldsShape::Union(_) => false,
369 FieldsShape::Array { count, .. } => {
370 *count > 0 && self.field(cx, 0).has_variant_dependent_padding(cx)
371 }
372 FieldsShape::Arbitrary { offsets, .. } => {
373 (0..offsets.len()).any(|i| self.field(cx, i).has_variant_dependent_padding(cx))
374 }
375 },
376 }
377 }
378
379 pub fn variant_independent_padding_ranges<C>(&self, cx: &C) -> Vec<Range<Size>>
387 where
388 Ty: TyAbiInterface<'a, C> + Copy,
389 {
390 let mut data = RangeSet::new();
391 self.add_data_ranges(cx, Size::ZERO, &mut data);
392
393 let mut uninit_ranges = Vec::new();
395 let mut covered_until = Size::ZERO;
396 for &(offset, size) in data.0.iter() {
397 if offset > covered_until {
398 uninit_ranges.push(covered_until..offset);
399 }
400 covered_until = Ord::max(covered_until, offset + size);
401 }
402
403 if self.size > covered_until {
405 uninit_ranges.push(covered_until..self.size);
406 }
407
408 uninit_ranges
409 }
410
411 pub fn variant_dependent_padding_ranges<C>(
415 &self,
416 cx: &C,
417 variant_index: VariantIdx,
418 ) -> Vec<Range<Size>>
419 where
420 Ty: TyAbiInterface<'a, C> + Copy,
421 {
422 let Variants::Multiple { .. } = self.variants else {
423 return Vec::new();
424 };
425
426 let mut any = RangeSet::new();
428 self.add_data_ranges(cx, Size::ZERO, &mut any);
429
430 let mut this = RangeSet::new();
432
433 let FieldsShape::Arbitrary { offsets, in_memory_order: _ } = &self.fields else {
435 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("a multi-variant layout should have `Arbitrary` fields")));
}unreachable!("a multi-variant layout should have `Arbitrary` fields")
436 };
437
438 for (field, &offset) in offsets.iter_enumerated() {
440 let field = self.field(cx, field.as_usize());
441 field.add_data_ranges(cx, offset, &mut this);
442 }
443
444 self.for_variant(cx, variant_index).add_data_ranges(cx, Size::ZERO, &mut this);
445
446 any.difference(&this).0.iter().map(|&(offset, size)| offset..offset + size).collect()
448 }
449
450 fn add_data_ranges<C>(self, cx: &C, base_offset: Size, out: &mut RangeSet<Size>)
454 where
455 Ty: TyAbiInterface<'a, C> + Copy,
456 {
457 if self.is_zst() {
458 return;
459 }
460
461 match &self.fields {
463 FieldsShape::Primitive => {
464 out.add_range(base_offset, self.size);
465 }
466 &FieldsShape::Union(field_count) => {
467 for field in 0..field_count.get() {
468 let field = self.field(cx, field);
469 field.add_data_ranges(cx, base_offset, out);
470 }
471 }
472 &FieldsShape::Array { stride, count } => {
473 let elem = self.field(cx, 0);
474
475 if elem.backend_repr.is_scalar() {
478 out.add_range(base_offset, elem.size * count);
479 } else {
480 for idx in 0..count {
482 elem.add_data_ranges(cx, base_offset + idx * stride, out);
483 }
484 }
485 }
486 FieldsShape::Arbitrary { offsets, in_memory_order: _ } => {
487 for (field, &offset) in offsets.iter_enumerated() {
488 let field = self.field(cx, field.as_usize());
489 field.add_data_ranges(cx, base_offset + offset, out);
490 }
491 }
492 }
493
494 match &self.variants {
496 Variants::Empty | Variants::Single { index: _ } => { }
497 Variants::Multiple { variants, .. } => {
498 for variant in variants.indices() {
499 let variant = self.for_variant(cx, variant);
500 variant.add_data_ranges(cx, base_offset, out);
501 }
502 }
503 }
504 }
505}