pub use Integer::*; pub use Primitive::*; use crate::json::{Json, ToJson}; use std::ops::Deref; use rustc_macros::HashStable_Generic; pub mod call; pub use rustc_abi::*; impl ToJson for Endian { fn to_json(&self) -> Json { self.as_str().to_json() } } /// The layout of a type, alongside the type itself. /// Provides various type traversal APIs (e.g., recursing into fields). /// /// Note that the layout is NOT guaranteed to always be identical /// to that obtained from `layout_of(ty)`, as we need to produce /// layouts for which Rust types do not exist, such as enum variants /// or synthetic fields of enums (i.e., discriminants) and fat pointers. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)] pub struct TyAndLayout<'a, Ty> { pub ty: Ty, pub layout: Layout<'a>, } impl<'a, Ty> Deref for TyAndLayout<'a, Ty> { type Target = &'a LayoutS; fn deref(&self) -> &&'a LayoutS { &self.layout.0.0 } } /// Trait that needs to be implemented by the higher-level type representation /// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality. pub trait TyAbiInterface<'a, C>: Sized { fn ty_and_layout_for_variant( this: TyAndLayout<'a, Self>, cx: &C, variant_index: VariantIdx, ) -> TyAndLayout<'a, Self>; fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>; fn ty_and_layout_pointee_info_at( this: TyAndLayout<'a, Self>, cx: &C, offset: Size, ) -> Option; fn is_adt(this: TyAndLayout<'a, Self>) -> bool; fn is_never(this: TyAndLayout<'a, Self>) -> bool; fn is_tuple(this: TyAndLayout<'a, Self>) -> bool; fn is_unit(this: TyAndLayout<'a, Self>) -> bool; } impl<'a, Ty> TyAndLayout<'a, Ty> { pub fn for_variant(self, cx: &C, variant_index: VariantIdx) -> Self where Ty: TyAbiInterface<'a, C>, { Ty::ty_and_layout_for_variant(self, cx, variant_index) } pub fn field(self, cx: &C, i: usize) -> Self where Ty: TyAbiInterface<'a, C>, { Ty::ty_and_layout_field(self, cx, i) } pub fn pointee_info_at(self, cx: &C, offset: Size) -> Option where Ty: TyAbiInterface<'a, C>, { Ty::ty_and_layout_pointee_info_at(self, cx, offset) } pub fn is_single_fp_element(self, cx: &C) -> bool where Ty: TyAbiInterface<'a, C>, C: HasDataLayout, { match self.abi { Abi::Scalar(scalar) => matches!(scalar.primitive(), F32 | F64), Abi::Aggregate { .. } => { if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 { self.field(cx, 0).is_single_fp_element(cx) } else { false } } _ => false, } } pub fn is_adt(self) -> bool where Ty: TyAbiInterface<'a, C>, { Ty::is_adt(self) } pub fn is_never(self) -> bool where Ty: TyAbiInterface<'a, C>, { Ty::is_never(self) } pub fn is_tuple(self) -> bool where Ty: TyAbiInterface<'a, C>, { Ty::is_tuple(self) } pub fn is_unit(self) -> bool where Ty: TyAbiInterface<'a, C>, { Ty::is_unit(self) } } impl<'a, Ty> TyAndLayout<'a, Ty> { /// Returns `true` if the layout corresponds to an unsized type. pub fn is_unsized(&self) -> bool { self.abi.is_unsized() } #[inline] pub fn is_sized(&self) -> bool { self.abi.is_sized() } /// Returns `true` if the type is a ZST and not unsized. pub fn is_zst(&self) -> bool { match self.abi { Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false, Abi::Uninhabited => self.size.bytes() == 0, Abi::Aggregate { sized } => sized && self.size.bytes() == 0, } } }