1#[cfg(feature = "nightly")]
2use crate::{BackendRepr, FieldsShape, Primitive, Size, TyAbiInterface, TyAndLayout, Variants};
3
4mod reg;
5
6pub use reg::{Reg, RegKind};
7
8#[derive(#[automatically_derived]
impl ::core::marker::Copy for HomogeneousAggregate { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for HomogeneousAggregate { }
#[automatically_derived]
impl ::core::clone::Clone for HomogeneousAggregate {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Reg>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for HomogeneousAggregate {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Homogeneous(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Homogeneous", &__self_0),
Self::NoData => ::core::fmt::Formatter::write_str(f, "NoData"),
}
}
}Debug)]
10pub enum HomogeneousAggregate {
11 Homogeneous(Reg),
14
15 NoData,
17}
18
19#[derive(#[automatically_derived]
impl ::core::marker::Copy for Heterogeneous { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Heterogeneous { }
#[automatically_derived]
impl ::core::clone::Clone for Heterogeneous {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Heterogeneous {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Heterogeneous")
}
}Debug)]
23pub struct Heterogeneous;
24
25impl HomogeneousAggregate {
26 pub fn unit(self) -> Option<Reg> {
29 match self {
30 HomogeneousAggregate::Homogeneous(reg) => Some(reg),
31 HomogeneousAggregate::NoData => None,
32 }
33 }
34
35 #[cfg(feature = "nightly")]
39 fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
40 match (self, other) {
41 (x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),
42
43 (HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => {
44 if a != b {
45 return Err(Heterogeneous);
46 }
47 Ok(self)
48 }
49 }
50 }
51}
52
53#[cfg(feature = "nightly")]
54impl<'a, Ty> TyAndLayout<'a, Ty> {
55 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("homogeneous_aggregate",
"rustc_abi::callconv", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/75a75c3e0a67d3fa3d03982775f5bb0356e7b510/compiler/rustc_abi/src/callconv.rs"),
::tracing_core::__macro_support::Option::Some(68u32),
::tracing_core::__macro_support::Option::Some("rustc_abi::callconv"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self")
}> =
::tracing::__macro_support::FieldName::new("self");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Result<HomogeneousAggregate, Heterogeneous> = loop {};
return __tracing_attr_fake_return;
}
{
match self.backend_repr {
BackendRepr::Scalar(scalar) => {
let kind =
match scalar.primitive() {
Primitive::Int(..) | Primitive::Pointer(_) =>
RegKind::Integer,
Primitive::Float(_) => RegKind::Float,
};
Ok(HomogeneousAggregate::Homogeneous(Reg {
kind,
size: self.size,
}))
}
BackendRepr::SimdVector { element, count: _ } => {
if !!self.is_zst() {
::core::panicking::panic("assertion failed: !self.is_zst()")
};
Ok(HomogeneousAggregate::Homogeneous(Reg {
kind: RegKind::Vector {
hint_vector_elem: element.primitive(),
},
size: self.size,
}))
}
BackendRepr::SimdScalableVector { .. } => {
{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("`homogeneous_aggregate` should not be called for scalable vectors")));
}
}
BackendRepr::ScalarPair { .. } | BackendRepr::Memory {
sized: true } => {
let from_fields_at =
|layout: Self, start: Size|
-> Result<(HomogeneousAggregate, Size), Heterogeneous>
{
let is_union =
match layout.fields {
FieldsShape::Primitive => {
{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("aggregates can\'t have `FieldsShape::Primitive`")));
}
}
FieldsShape::Array { count, .. } => {
{
match (&start, &Size::ZERO) {
(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);
}
}
}
};
let result =
if count > 0 {
layout.field(cx, 0).homogeneous_aggregate(cx)?
} else { HomogeneousAggregate::NoData };
return Ok((result, layout.size));
}
FieldsShape::Union(_) => true,
FieldsShape::Arbitrary { .. } => false,
};
let mut result = HomogeneousAggregate::NoData;
let mut total = start;
for i in 0..layout.fields.count() {
let field = layout.field(cx, i);
if field.is_1zst() { continue; }
if !is_union && total != layout.fields.offset(i) {
return Err(Heterogeneous);
}
result = result.merge(field.homogeneous_aggregate(cx)?)?;
let size = field.size;
if is_union {
total = total.max(size);
} else { total += size; }
}
Ok((result, total))
};
let (mut result, mut total) =
from_fields_at(*self, Size::ZERO)?;
match &self.variants {
Variants::Single { .. } | Variants::Empty => {}
Variants::Multiple { variants, .. } => {
let variant_start = total;
for variant_idx in variants.indices() {
let (variant_result, variant_total) =
from_fields_at(self.for_variant(cx, variant_idx),
variant_start)?;
result = result.merge(variant_result)?;
total = total.max(variant_total);
}
}
}
if total != self.size {
Err(Heterogeneous)
} else {
match result {
HomogeneousAggregate::Homogeneous(_) => {
{
match (&total, &Size::ZERO) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
}
HomogeneousAggregate::NoData => {
{
match (&total, &Size::ZERO) {
(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);
}
}
}
};
}
}
Ok(result)
}
}
BackendRepr::Memory { sized: false } => Err(Heterogeneous),
}
}
}
}#[tracing::instrument(skip(cx), level = "debug")]
69 pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
70 where
71 Ty: TyAbiInterface<'a, C> + Copy,
72 {
73 match self.backend_repr {
74 BackendRepr::Scalar(scalar) => {
76 let kind = match scalar.primitive() {
77 Primitive::Int(..) | Primitive::Pointer(_) => RegKind::Integer,
78 Primitive::Float(_) => RegKind::Float,
79 };
80 Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
81 }
82
83 BackendRepr::SimdVector { element, count: _ } => {
84 assert!(!self.is_zst());
85
86 Ok(HomogeneousAggregate::Homogeneous(Reg {
87 kind: RegKind::Vector { hint_vector_elem: element.primitive() },
88 size: self.size,
89 }))
90 }
91
92 BackendRepr::SimdScalableVector { .. } => {
93 unreachable!("`homogeneous_aggregate` should not be called for scalable vectors")
94 }
95
96 BackendRepr::ScalarPair { .. } | BackendRepr::Memory { sized: true } => {
97 let from_fields_at =
100 |layout: Self,
101 start: Size|
102 -> Result<(HomogeneousAggregate, Size), Heterogeneous> {
103 let is_union = match layout.fields {
104 FieldsShape::Primitive => {
105 unreachable!("aggregates can't have `FieldsShape::Primitive`")
106 }
107 FieldsShape::Array { count, .. } => {
108 assert_eq!(start, Size::ZERO);
109
110 let result = if count > 0 {
111 layout.field(cx, 0).homogeneous_aggregate(cx)?
112 } else {
113 HomogeneousAggregate::NoData
114 };
115 return Ok((result, layout.size));
116 }
117 FieldsShape::Union(_) => true,
118 FieldsShape::Arbitrary { .. } => false,
119 };
120
121 let mut result = HomogeneousAggregate::NoData;
122 let mut total = start;
123
124 for i in 0..layout.fields.count() {
125 let field = layout.field(cx, i);
126 if field.is_1zst() {
127 continue;
130 }
131
132 if !is_union && total != layout.fields.offset(i) {
133 return Err(Heterogeneous);
135 }
136
137 result = result.merge(field.homogeneous_aggregate(cx)?)?;
138
139 let size = field.size;
141 if is_union {
142 total = total.max(size);
143 } else {
144 total += size;
145 }
146 }
147
148 Ok((result, total))
149 };
150
151 let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
152
153 match &self.variants {
154 Variants::Single { .. } | Variants::Empty => {}
155 Variants::Multiple { variants, .. } => {
156 let variant_start = total;
169 for variant_idx in variants.indices() {
170 let (variant_result, variant_total) =
171 from_fields_at(self.for_variant(cx, variant_idx), variant_start)?;
172
173 result = result.merge(variant_result)?;
174 total = total.max(variant_total);
175 }
176 }
177 }
178
179 if total != self.size {
181 Err(Heterogeneous)
182 } else {
183 match result {
184 HomogeneousAggregate::Homogeneous(_) => {
185 assert_ne!(total, Size::ZERO);
186 }
187 HomogeneousAggregate::NoData => {
188 assert_eq!(total, Size::ZERO);
189 }
190 }
191 Ok(result)
192 }
193 }
194 BackendRepr::Memory { sized: false } => Err(Heterogeneous),
195 }
196 }
197}