Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/layout.rs')
-rw-r--r--crates/hir-ty/src/layout.rs236
1 files changed, 68 insertions, 168 deletions
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 6b5c712159..bbd419d965 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -6,16 +6,14 @@ use base_db::ra_salsa::Cycle;
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
use hir_def::{
layout::{
- BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError,
- LayoutData, Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout,
- WrappingRange,
+ Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData, Primitive,
+ ReprOptions, Scalar, StructKind, TargetDataLayout, WrappingRange,
},
LocalFieldId, StructId,
};
use la_arena::{Idx, RawIdx};
use rustc_abi::AddressSpace;
-use rustc_hashes::Hash64;
-use rustc_index::{IndexSlice, IndexVec};
+use rustc_index::IndexVec;
use triomphe::Arc;
@@ -23,7 +21,6 @@ use crate::{
consteval::try_const_usize,
db::{HirDatabase, InternedClosure},
infer::normalize,
- layout::adt::struct_variant_idx,
utils::ClosureSubst,
Interner, ProjectionTy, Substitution, TraitEnvironment, Ty,
};
@@ -125,82 +122,34 @@ impl<'a> LayoutCx<'a> {
}
}
-// FIXME: move this to the `rustc_abi`.
fn layout_of_simd_ty(
db: &dyn HirDatabase,
id: StructId,
+ repr_packed: bool,
subst: &Substitution,
env: Arc<TraitEnvironment>,
dl: &TargetDataLayout,
) -> Result<Arc<Layout>, LayoutError> {
- let fields = db.field_types(id.into());
-
- // Supported SIMD vectors are homogeneous ADTs with at least one field:
+ // Supported SIMD vectors are homogeneous ADTs with exactly one array field:
//
- // * #[repr(simd)] struct S(T, T, T, T);
- // * #[repr(simd)] struct S { it: T, y: T, z: T, w: T }
// * #[repr(simd)] struct S([T; 4])
//
// where T is a primitive scalar (integer/float/pointer).
-
- let f0_ty = match fields.iter().next() {
- Some(it) => it.1.clone().substitute(Interner, subst),
- None => return Err(LayoutError::InvalidSimdType),
- };
-
- // The element type and number of elements of the SIMD vector
- // are obtained from:
- //
- // * the element type and length of the single array field, if
- // the first field is of array type, or
- //
- // * the homogeneous field type and the number of fields.
- let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
- // Extract the number of elements from the layout of the array field:
- let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields
- else {
- return Err(LayoutError::Unknown);
- };
-
- (e_ty.clone(), count, true)
- } else {
- // First ADT field is not an array:
- (f0_ty, fields.iter().count() as u64, false)
+ let fields = db.field_types(id.into());
+ let mut fields = fields.iter();
+ let Some(TyKind::Array(e_ty, e_len)) = fields
+ .next()
+ .filter(|_| fields.next().is_none())
+ .map(|f| f.1.clone().substitute(Interner, subst).kind(Interner).clone())
+ else {
+ return Err(LayoutError::InvalidSimdType);
};
- // Compute the ABI of the element type:
+ let e_len = try_const_usize(db, &e_len).ok_or(LayoutError::HasErrorConst)? as u64;
let e_ly = db.layout_of_ty(e_ty, env)?;
- let BackendRepr::Scalar(e_abi) = e_ly.backend_repr else {
- return Err(LayoutError::Unknown);
- };
-
- // Compute the size and alignment of the vector:
- let size = e_ly
- .size
- .checked_mul(e_len, dl)
- .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
- let align = dl.llvmlike_vector_align(size);
- let size = size.align_to(align.abi);
-
- // Compute the placement of the vector fields:
- let fields = if is_array {
- FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }
- } else {
- FieldsShape::Array { stride: e_ly.size, count: e_len }
- };
- Ok(Arc::new(Layout {
- variants: Variants::Single { index: struct_variant_idx() },
- fields,
- backend_repr: BackendRepr::SimdVector { element: e_abi, count: e_len },
- largest_niche: e_ly.largest_niche,
- uninhabited: false,
- size,
- align,
- max_repr_align: None,
- unadjusted_abi_align: align.abi,
- randomization_seed: Hash64::ZERO,
- }))
+ let cx = LayoutCx::new(dl);
+ Ok(Arc::new(cx.calc.simd_type(e_ly, e_len, repr_packed)?))
}
pub fn layout_of_ty_query(
@@ -215,13 +164,14 @@ pub fn layout_of_ty_query(
let dl = &*target;
let cx = LayoutCx::new(dl);
let ty = normalize(db, trait_env.clone(), ty);
- let result = match ty.kind(Interner) {
+ let kind = ty.kind(Interner);
+ let result = match kind {
TyKind::Adt(AdtId(def), subst) => {
if let hir_def::AdtId::StructId(s) = def {
let data = db.struct_data(*s);
let repr = data.repr.unwrap_or_default();
if repr.simd() {
- return layout_of_simd_ty(db, *s, subst, trait_env, &target);
+ return layout_of_simd_ty(db, *s, repr.packed(), subst, trait_env, &target);
}
};
return db.layout_of_adt(*def, subst.clone(), trait_env);
@@ -241,42 +191,51 @@ pub fn layout_of_ty_query(
valid_range: WrappingRange { start: 0, end: 0x10FFFF },
},
),
- chalk_ir::Scalar::Int(i) => scalar(
+ chalk_ir::Scalar::Int(i) => Layout::scalar(
dl,
- Primitive::Int(
- match i {
- IntTy::Isize => dl.ptr_sized_integer(),
- IntTy::I8 => Integer::I8,
- IntTy::I16 => Integer::I16,
- IntTy::I32 => Integer::I32,
- IntTy::I64 => Integer::I64,
- IntTy::I128 => Integer::I128,
- },
- true,
+ scalar_unit(
+ dl,
+ Primitive::Int(
+ match i {
+ IntTy::Isize => dl.ptr_sized_integer(),
+ IntTy::I8 => Integer::I8,
+ IntTy::I16 => Integer::I16,
+ IntTy::I32 => Integer::I32,
+ IntTy::I64 => Integer::I64,
+ IntTy::I128 => Integer::I128,
+ },
+ true,
+ ),
),
),
- chalk_ir::Scalar::Uint(i) => scalar(
+ chalk_ir::Scalar::Uint(i) => Layout::scalar(
dl,
- Primitive::Int(
- match i {
- UintTy::Usize => dl.ptr_sized_integer(),
- UintTy::U8 => Integer::I8,
- UintTy::U16 => Integer::I16,
- UintTy::U32 => Integer::I32,
- UintTy::U64 => Integer::I64,
- UintTy::U128 => Integer::I128,
- },
- false,
+ scalar_unit(
+ dl,
+ Primitive::Int(
+ match i {
+ UintTy::Usize => dl.ptr_sized_integer(),
+ UintTy::U8 => Integer::I8,
+ UintTy::U16 => Integer::I16,
+ UintTy::U32 => Integer::I32,
+ UintTy::U64 => Integer::I64,
+ UintTy::U128 => Integer::I128,
+ },
+ false,
+ ),
),
),
- chalk_ir::Scalar::Float(f) => scalar(
+ chalk_ir::Scalar::Float(f) => Layout::scalar(
dl,
- Primitive::Float(match f {
- FloatTy::F16 => Float::F16,
- FloatTy::F32 => Float::F32,
- FloatTy::F64 => Float::F64,
- FloatTy::F128 => Float::F128,
- }),
+ scalar_unit(
+ dl,
+ Primitive::Float(match f {
+ FloatTy::F16 => Float::F16,
+ FloatTy::F32 => Float::F32,
+ FloatTy::F64 => Float::F64,
+ FloatTy::F128 => Float::F128,
+ }),
+ ),
),
},
TyKind::Tuple(len, tys) => {
@@ -293,56 +252,16 @@ pub fn layout_of_ty_query(
TyKind::Array(element, count) => {
let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64;
let element = db.layout_of_ty(element.clone(), trait_env)?;
- let size = element
- .size
- .checked_mul(count, dl)
- .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
-
- let backend_repr = BackendRepr::Memory { sized: true };
-
- let largest_niche = if count != 0 { element.largest_niche } else { None };
- let uninhabited = if count != 0 { element.uninhabited } else { false };
-
- Layout {
- variants: Variants::Single { index: struct_variant_idx() },
- fields: FieldsShape::Array { stride: element.size, count },
- backend_repr,
- largest_niche,
- uninhabited,
- align: element.align,
- size,
- max_repr_align: None,
- unadjusted_abi_align: element.align.abi,
- randomization_seed: Hash64::ZERO,
- }
+ cx.calc.array_like::<_, _, ()>(&element, Some(count))?
}
TyKind::Slice(element) => {
let element = db.layout_of_ty(element.clone(), trait_env)?;
- Layout {
- variants: Variants::Single { index: struct_variant_idx() },
- fields: FieldsShape::Array { stride: element.size, count: 0 },
- backend_repr: BackendRepr::Memory { sized: false },
- largest_niche: None,
- uninhabited: false,
- align: element.align,
- size: Size::ZERO,
- max_repr_align: None,
- unadjusted_abi_align: element.align.abi,
- randomization_seed: Hash64::ZERO,
- }
+ cx.calc.array_like::<_, _, ()>(&element, None)?
+ }
+ TyKind::Str => {
+ let element = scalar_unit(dl, Primitive::Int(Integer::I8, false));
+ cx.calc.array_like::<_, _, ()>(&Layout::scalar(dl, element), None)?
}
- TyKind::Str => Layout {
- variants: Variants::Single { index: struct_variant_idx() },
- fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
- backend_repr: BackendRepr::Memory { sized: false },
- largest_niche: None,
- uninhabited: false,
- align: dl.i8_align,
- size: Size::ZERO,
- max_repr_align: None,
- unadjusted_abi_align: dl.i8_align.abi,
- randomization_seed: Hash64::ZERO,
- },
// Potentially-wide pointers.
TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => {
let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA));
@@ -380,17 +299,12 @@ pub fn layout_of_ty_query(
};
// Effectively a (ptr, meta) tuple.
- cx.calc.scalar_pair(data_ptr, metadata)
+ LayoutData::scalar_pair(dl, data_ptr, metadata)
}
- TyKind::FnDef(_, _) => layout_of_unit(&cx)?,
- TyKind::Never => cx.calc.layout_of_never_type(),
- TyKind::Dyn(_) | TyKind::Foreign(_) => {
- let mut unit = layout_of_unit(&cx)?;
- match &mut unit.backend_repr {
- BackendRepr::Memory { sized } => *sized = false,
- _ => return Err(LayoutError::Unknown),
- }
- unit
+ TyKind::Never => LayoutData::never_type(dl),
+ TyKind::FnDef(..) | TyKind::Dyn(_) | TyKind::Foreign(_) => {
+ let sized = matches!(kind, TyKind::FnDef(..));
+ LayoutData::unit(dl, sized)
}
TyKind::Function(_) => {
let mut ptr = scalar_unit(dl, Primitive::Pointer(dl.instruction_address_space));
@@ -462,16 +376,6 @@ pub fn layout_of_ty_recover(
Err(LayoutError::RecursiveTypeWithoutIndirection)
}
-fn layout_of_unit(cx: &LayoutCx<'_>) -> Result<Layout, LayoutError> {
- cx.calc
- .univariant::<RustcFieldIdx, RustcEnumVariantIdx, &&Layout>(
- IndexSlice::empty(),
- &ReprOptions::default(),
- StructKind::AlwaysSized,
- )
- .map_err(Into::into)
-}
-
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
match pointee.kind(Interner) {
TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), subst) => {
@@ -502,9 +406,5 @@ fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {
Scalar::Initialized { value, valid_range: WrappingRange::full(value.size(dl)) }
}
-fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout {
- Layout::scalar(dl, scalar_unit(dl, value))
-}
-
#[cfg(test)]
mod tests;