Skip to main content

rustc_abi/callconv/
reg.rs

1#[cfg(feature = "nightly")]
2use rustc_macros::StableHash;
3
4use crate::{Align, Float, HasDataLayout, Integer, Primitive, Size};
5
6/// The "kind" of backend type, which combined with a [`Size`] forms a [`Reg`].
7#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for RegKind {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    RegKind::Integer => {}
                    RegKind::Float => {}
                    RegKind::PpcF128 => {}
                    RegKind::Vector { hint_vector_elem: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash))]
8#[derive(#[automatically_derived]
impl ::core::marker::Copy for RegKind { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for RegKind { }
#[automatically_derived]
impl ::core::clone::Clone for RegKind {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Primitive>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for RegKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for RegKind {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Vector { hint_vector_elem: __self_0 }, Self::Vector {
                    hint_vector_elem: __arg1_0 }) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RegKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Primitive>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for RegKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state);
        match self {
            Self::Vector { hint_vector_elem: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for RegKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Integer => ::core::fmt::Formatter::write_str(f, "Integer"),
            Self::Float => ::core::fmt::Formatter::write_str(f, "Float"),
            Self::PpcF128 => ::core::fmt::Formatter::write_str(f, "PpcF128"),
            Self::Vector { hint_vector_elem: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Vector", "hint_vector_elem", &__self_0),
        }
    }
}Debug)]
9pub enum RegKind {
10    Integer,
11    Float,
12    /// The IBM extended-precision format: a pair of `f64`s, each passed in its own register.
13    /// This variant is needed to distinguish IEEE f128 and IBM f128 in the backends.
14    ///
15    /// Only used on PowerPC targets.
16    PpcF128,
17    Vector {
18        /// The `hint_vector_elem` is strictly for optimization purposes. E.g. it can be used by
19        /// a codegen backend to prevent extra bitcasts that obscure a pattern. Alternatively,
20        /// it can be safely ignored by always picking i8.
21        hint_vector_elem: Primitive,
22    },
23}
24
25impl RegKind {
26    pub fn from_primitive(primitive: Primitive) -> Self {
27        match primitive {
28            Primitive::Int(..) | Primitive::Pointer(_) => RegKind::Integer,
29            Primitive::Float(Float::PpcF128) => RegKind::PpcF128,
30            Primitive::Float(Float::F16 | Float::F16B | Float::F32 | Float::F64 | Float::F128) => {
31                RegKind::Float
32            }
33        }
34    }
35}
36
37/// A combination of a [`RegKind`] and a [`Size`] that represents a builtin type in the backend.
38#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for Reg {
            #[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 {
                    Reg { kind: ref __binding_0, size: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash))]
39#[derive(#[automatically_derived]
impl ::core::marker::Copy for Reg { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Reg { }
#[automatically_derived]
impl ::core::clone::Clone for Reg {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<RegKind>;
        let _: ::core::clone::AssertParamIsClone<Size>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Reg { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Reg {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.kind == other.kind && self.size == other.size
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Reg {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<RegKind>;
        let _: ::core::cmp::AssertParamIsEq<Size>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Reg {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.kind, state);
        ::core::hash::Hash::hash(&self.size, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Reg {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Reg", "kind",
            &self.kind, "size", &&self.size)
    }
}Debug)]
40pub struct Reg {
41    pub kind: RegKind,
42    pub size: Size,
43}
44
45macro_rules! reg_ctor {
46    ($name:ident, $kind:ident, $bits:expr) => {
47        pub fn $name() -> Reg {
48            Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
49        }
50    };
51}
52
53impl Reg {
54    pub fn i8() -> Reg {
    Reg { kind: RegKind::Integer, size: Size::from_bits(8) }
}reg_ctor!(i8, Integer, 8);
55    pub fn i16() -> Reg {
    Reg { kind: RegKind::Integer, size: Size::from_bits(16) }
}reg_ctor!(i16, Integer, 16);
56    pub fn i32() -> Reg {
    Reg { kind: RegKind::Integer, size: Size::from_bits(32) }
}reg_ctor!(i32, Integer, 32);
57    pub fn i64() -> Reg {
    Reg { kind: RegKind::Integer, size: Size::from_bits(64) }
}reg_ctor!(i64, Integer, 64);
58    pub fn i128() -> Reg {
    Reg { kind: RegKind::Integer, size: Size::from_bits(128) }
}reg_ctor!(i128, Integer, 128);
59
60    pub fn f16() -> Reg {
    Reg { kind: RegKind::Float, size: Size::from_bits(16) }
}reg_ctor!(f16, Float, 16);
61    pub fn f32() -> Reg {
    Reg { kind: RegKind::Float, size: Size::from_bits(32) }
}reg_ctor!(f32, Float, 32);
62    pub fn f64() -> Reg {
    Reg { kind: RegKind::Float, size: Size::from_bits(64) }
}reg_ctor!(f64, Float, 64);
63    pub fn f128() -> Reg {
    Reg { kind: RegKind::Float, size: Size::from_bits(128) }
}reg_ctor!(f128, Float, 128);
64
65    /// A vector of the given size with an unknown (and irrelevant) element type.
66    pub fn opaque_vector(size: Size) -> Reg {
67        // Default to an i8 vector of the given size.
68        Reg { kind: RegKind::Vector { hint_vector_elem: Primitive::Int(Integer::I8, true) }, size }
69    }
70}
71
72impl Reg {
73    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
74        let dl = cx.data_layout();
75        match self.kind {
76            RegKind::Integer => match self.size.bits() {
77                1 => dl.i1_align,
78                2..=8 => dl.i8_align,
79                9..=16 => dl.i16_align,
80                17..=32 => dl.i32_align,
81                33..=64 => dl.i64_align,
82                65..=128 => dl.i128_align,
83                _ => {
    ::core::panicking::panic_fmt(format_args!("unsupported integer: {0:?}",
            self));
}panic!("unsupported integer: {self:?}"),
84            },
85            RegKind::Float => match self.size.bits() {
86                16 => dl.f16_align,
87                32 => dl.f32_align,
88                64 => dl.f64_align,
89                128 => dl.f128_align,
90                _ => {
    ::core::panicking::panic_fmt(format_args!("unsupported float: {0:?}",
            self));
}panic!("unsupported float: {self:?}"),
91            },
92            RegKind::PpcF128 => dl.f128_align,
93            RegKind::Vector { .. } => dl.rust_vector_align(self.size),
94        }
95    }
96}