Skip to main content

rustc_target/callconv/
mod.rs

1use std::{fmt, iter};
2
3use arrayvec::ArrayVec;
4use rustc_abi::{
5    AddressSpace, Align, BackendRepr, CanonAbi, ExternAbi, FieldsShape, HasDataLayout, Primitive,
6    Reg, RegKind, Scalar, Size, TyAbiInterface, TyAndLayout, Variants,
7};
8use rustc_macros::StableHash;
9
10pub use crate::spec::AbiMap;
11use crate::spec::{Arch, HasTargetSpec, HasX86AbiOpt};
12
13mod aarch64;
14mod amdgpu;
15mod arm;
16mod avr;
17mod bpf;
18mod csky;
19mod hexagon;
20mod loongarch;
21mod m68k;
22mod mips;
23mod mips64;
24mod msp430;
25mod nvptx64;
26mod powerpc;
27mod powerpc64;
28mod riscv;
29mod s390x;
30mod sparc;
31mod sparc64;
32mod wasm;
33mod x86;
34mod x86_64;
35mod x86_win32;
36mod x86_win64;
37mod xtensa;
38
39#[derive(#[automatically_derived]
impl ::core::clone::Clone for PassMode {
    #[inline]
    fn clone(&self) -> PassMode {
        match self {
            PassMode::Ignore => PassMode::Ignore,
            PassMode::Direct(__self_0) =>
                PassMode::Direct(::core::clone::Clone::clone(__self_0)),
            PassMode::Pair(__self_0, __self_1) =>
                PassMode::Pair(::core::clone::Clone::clone(__self_0),
                    ::core::clone::Clone::clone(__self_1)),
            PassMode::Cast { pad_i32_count: __self_0, cast: __self_1 } =>
                PassMode::Cast {
                    pad_i32_count: ::core::clone::Clone::clone(__self_0),
                    cast: ::core::clone::Clone::clone(__self_1),
                },
            PassMode::Indirect {
                attrs: __self_0, meta_attrs: __self_1, on_stack: __self_2 } =>
                PassMode::Indirect {
                    attrs: ::core::clone::Clone::clone(__self_0),
                    meta_attrs: ::core::clone::Clone::clone(__self_1),
                    on_stack: ::core::clone::Clone::clone(__self_2),
                },
        }
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for PassMode { }
#[automatically_derived]
impl ::core::cmp::PartialEq for PassMode {
    #[inline]
    fn eq(&self, other: &PassMode) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (PassMode::Direct(__self_0), PassMode::Direct(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (PassMode::Pair(__self_0, __self_1),
                    PassMode::Pair(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (PassMode::Cast { pad_i32_count: __self_0, cast: __self_1 },
                    PassMode::Cast { pad_i32_count: __arg1_0, cast: __arg1_1 })
                    => __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (PassMode::Indirect {
                    attrs: __self_0, meta_attrs: __self_1, on_stack: __self_2 },
                    PassMode::Indirect {
                    attrs: __arg1_0, meta_attrs: __arg1_1, on_stack: __arg1_2 })
                    =>
                    __self_2 == __arg1_2 && __self_0 == __arg1_0 &&
                        __self_1 == __arg1_1,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PassMode {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ArgAttributes>;
        let _: ::core::cmp::AssertParamIsEq<u8>;
        let _: ::core::cmp::AssertParamIsEq<Box<CastTarget>>;
        let _: ::core::cmp::AssertParamIsEq<Option<ArgAttributes>>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for PassMode {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            PassMode::Direct(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            PassMode::Pair(__self_0, __self_1) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            PassMode::Cast { pad_i32_count: __self_0, cast: __self_1 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            PassMode::Indirect {
                attrs: __self_0, meta_attrs: __self_1, on_stack: __self_2 } =>
                {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state);
                ::core::hash::Hash::hash(__self_2, state)
            }
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for PassMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            PassMode::Ignore =>
                ::core::fmt::Formatter::write_str(f, "Ignore"),
            PassMode::Direct(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Direct",
                    &__self_0),
            PassMode::Pair(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "Pair",
                    __self_0, &__self_1),
            PassMode::Cast { pad_i32_count: __self_0, cast: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Cast",
                    "pad_i32_count", __self_0, "cast", &__self_1),
            PassMode::Indirect {
                attrs: __self_0, meta_attrs: __self_1, on_stack: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "Indirect", "attrs", __self_0, "meta_attrs", __self_1,
                    "on_stack", &__self_2),
        }
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for PassMode {
            #[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 {
                    PassMode::Ignore => {}
                    PassMode::Direct(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    PassMode::Pair(ref __binding_0, ref __binding_1) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    PassMode::Cast {
                        pad_i32_count: ref __binding_0, cast: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    PassMode::Indirect {
                        attrs: ref __binding_0,
                        meta_attrs: ref __binding_1,
                        on_stack: ref __binding_2 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
40pub enum PassMode {
41    /// Ignore the argument.
42    ///
43    /// The argument is a ZST.
44    Ignore,
45    /// Pass the argument directly.
46    ///
47    /// The argument has a layout abi of `Scalar` or `Vector`.
48    /// Unfortunately due to past mistakes, in rare cases on wasm, it can also be `Aggregate`.
49    /// This is bad since it leaks LLVM implementation details into the ABI.
50    /// (Also see <https://github.com/rust-lang/rust/issues/115666>.)
51    Direct(ArgAttributes),
52    /// Pass a pair's elements directly in two arguments.
53    ///
54    /// The argument has a layout abi of `ScalarPair`.
55    Pair(ArgAttributes, ArgAttributes),
56    /// Pass the argument after casting it. See the `CastTarget` docs for details.
57    ///
58    /// `pad_i32` indicates how many `Reg::i32()` dummy arguments are emitted before the real
59    /// argument.
60    Cast { pad_i32_count: u8, cast: Box<CastTarget> },
61    /// Pass the argument indirectly via a hidden pointer.
62    ///
63    /// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized
64    /// argument. (This is the only mode that supports unsized arguments.)
65    ///
66    /// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to
67    /// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument
68    /// attribute. The `byval` argument will use a byte array with the same size as the Rust type
69    /// (which ensures that padding is preserved and that we do not rely on LLVM's struct layout),
70    /// and will use the alignment specified in `attrs.pointee_align` (if `Some`) or the type's
71    /// alignment (if `None`). This means that the alignment will not always
72    /// match the Rust type's alignment; see documentation of `pass_by_stack_offset` for more info.
73    ///
74    /// `on_stack` cannot be true for unsized arguments, i.e., when `meta_attrs` is `Some`.
75    Indirect { attrs: ArgAttributes, meta_attrs: Option<ArgAttributes>, on_stack: bool },
76}
77
78impl PassMode {
79    /// Checks if these two `PassMode` are equal enough to be considered "the same for all
80    /// function call ABIs". However, the `Layout` can also impact ABI decisions,
81    /// so that needs to be compared as well!
82    pub fn eq_abi(&self, other: &Self) -> bool {
83        match (self, other) {
84            (PassMode::Ignore, PassMode::Ignore) => true,
85            (PassMode::Direct(a1), PassMode::Direct(a2)) => a1.eq_abi(a2),
86            (PassMode::Pair(a1, b1), PassMode::Pair(a2, b2)) => a1.eq_abi(a2) && b1.eq_abi(b2),
87            (
88                PassMode::Cast { cast: c1, pad_i32_count: pad1 },
89                PassMode::Cast { cast: c2, pad_i32_count: pad2 },
90            ) => c1.eq_abi(c2) && pad1 == pad2,
91            (
92                PassMode::Indirect { attrs: a1, meta_attrs: None, on_stack: s1 },
93                PassMode::Indirect { attrs: a2, meta_attrs: None, on_stack: s2 },
94            ) => a1.eq_abi(a2) && s1 == s2,
95            (
96                PassMode::Indirect { attrs: a1, meta_attrs: Some(e1), on_stack: s1 },
97                PassMode::Indirect { attrs: a2, meta_attrs: Some(e2), on_stack: s2 },
98            ) => a1.eq_abi(a2) && e1.eq_abi(e2) && s1 == s2,
99            _ => false,
100        }
101    }
102}
103
104// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
105// of this module
106pub use attr_impl::ArgAttribute;
107
108#[allow(non_upper_case_globals)]
109#[allow(unused)]
110mod attr_impl {
111    use rustc_macros::StableHash;
112
113    // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
114    #[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ArgAttribute { }
#[automatically_derived]
impl ::core::clone::Clone for ArgAttribute {
    #[inline]
    fn clone(&self) -> ArgAttribute {
        let _: ::core::clone::AssertParamIsClone<u16>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ArgAttribute { }Copy, #[automatically_derived]
impl ::core::default::Default for ArgAttribute {
    #[inline]
    fn default() -> ArgAttribute {
        ArgAttribute(::core::default::Default::default())
    }
}Default, #[automatically_derived]
impl ::core::hash::Hash for ArgAttribute {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for ArgAttribute { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ArgAttribute {
    #[inline]
    fn eq(&self, other: &ArgAttribute) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ArgAttribute {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u16>;
    }
}Eq, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ArgAttribute
            {
            #[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 {
                    ArgAttribute(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
115    pub struct ArgAttribute(u16);
116    impl ArgAttribute {
    #[allow(deprecated, non_upper_case_globals,)]
    pub const CapturesNone: Self = Self::from_bits_retain(0b111);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const CapturesAddress: Self = Self::from_bits_retain(0b110);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const CapturesReadOnly: Self = Self::from_bits_retain(0b100);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const NoAlias: Self = Self::from_bits_retain(1 << 3);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const NonNull: Self = Self::from_bits_retain(1 << 4);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const ReadOnly: Self = Self::from_bits_retain(1 << 5);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const InReg: Self = Self::from_bits_retain(1 << 6);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const NoUndef: Self = Self::from_bits_retain(1 << 7);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const Writable: Self = Self::from_bits_retain(1 << 8);
    #[doc =
    r" It is UB for this pointer or any pointer derived from it to be used for"]
    #[doc =
    r" deallocation (except for zero-sized deallocation) while the function is"]
    #[doc =
    r" executing. Only valid on arguments (including return values that are passed"]
    #[doc = r" indirectly as arguments)."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const NoFree: Self = Self::from_bits_retain(1 << 9);
}
impl ::bitflags::Flags for ArgAttribute {
    const FLAGS: &'static [::bitflags::Flag<ArgAttribute>] =
        &[{

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("CapturesNone",
                            ArgAttribute::CapturesNone)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("CapturesAddress",
                            ArgAttribute::CapturesAddress)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("CapturesReadOnly",
                            ArgAttribute::CapturesReadOnly)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("NoAlias", ArgAttribute::NoAlias)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("NonNull", ArgAttribute::NonNull)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("ReadOnly", ArgAttribute::ReadOnly)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("InReg", ArgAttribute::InReg)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("NoUndef", ArgAttribute::NoUndef)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("Writable", ArgAttribute::Writable)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("NoFree", ArgAttribute::NoFree)
                    }];
    type Bits = u16;
    fn bits(&self) -> u16 { ArgAttribute::bits(self) }
    fn from_bits_retain(bits: u16) -> ArgAttribute {
        ArgAttribute::from_bits_retain(bits)
    }
}
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy ::
assign_op_pattern, clippy :: iter_without_into_iter,)]
const _: () =
    {
        #[allow(dead_code, deprecated, unused_attributes)]
        impl ArgAttribute {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u16 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self {
                let mut truncated = <u16 as ::bitflags::Bits>::EMPTY;
                let mut i = 0;
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ArgAttribute as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                let _ = i;
                Self(truncated)
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u16 { self.0 }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[inline]
            pub const fn from_bits(bits: u16)
                -> ::bitflags::__private::core::option::Option<Self> {
                let truncated = Self::from_bits_truncate(bits).0;
                if truncated == bits {
                    ::bitflags::__private::core::option::Option::Some(Self(bits))
                } else { ::bitflags::__private::core::option::Option::None }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u16) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u16) -> Self { Self(bits) }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[inline]
            pub fn from_name(name: &str)
                -> ::bitflags::__private::core::option::Option<Self> {
                {
                    if name == "CapturesNone" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::CapturesNone.bits()));
                    }
                };
                ;
                {
                    if name == "CapturesAddress" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::CapturesAddress.bits()));
                    }
                };
                ;
                {
                    if name == "CapturesReadOnly" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::CapturesReadOnly.bits()));
                    }
                };
                ;
                {
                    if name == "NoAlias" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::NoAlias.bits()));
                    }
                };
                ;
                {
                    if name == "NonNull" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::NonNull.bits()));
                    }
                };
                ;
                {
                    if name == "ReadOnly" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::ReadOnly.bits()));
                    }
                };
                ;
                {
                    if name == "InReg" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::InReg.bits()));
                    }
                };
                ;
                {
                    if name == "NoUndef" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::NoUndef.bits()));
                    }
                };
                ;
                {
                    if name == "Writable" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::Writable.bits()));
                    }
                };
                ;
                {
                    if name == "NoFree" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ArgAttribute::NoFree.bits()));
                    }
                };
                ;
                let _ = name;
                ::bitflags::__private::core::option::Option::None
            }
            /// Whether all bits in this flags value are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool {
                self.0 == <u16 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool {
                Self::all().0 | self.0 == self.0
            }
            /// Whether any set bits in a source flags value are also set in a target flags value.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0 & other.0 != <u16 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all set bits in a source flags value are also set in a target flags value.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0 & other.0 == other.0
            }
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            pub fn insert(&mut self, other: Self) {
                *self = Self(self.0).union(other);
            }
            /// The intersection of a source flags value with the complement of a target flags
            /// value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) {
                *self = Self(self.0).difference(other);
            }
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            pub fn toggle(&mut self, other: Self) {
                *self = Self(self.0).symmetric_difference(other);
            }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                if value { self.insert(other); } else { self.remove(other); }
            }
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0 & other.0)
            }
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0 | other.0)
            }
            /// The intersection of a source flags value with the complement of a target flags
            /// value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0 & !other.0)
            }
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0 ^ other.0)
            }
            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
            #[inline]
            #[must_use]
            pub const fn complement(self) -> Self {
                Self::from_bits_truncate(!self.0)
            }
        }
        impl ::bitflags::__private::core::fmt::Binary for ArgAttribute {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::Octal for ArgAttribute {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::LowerHex for ArgAttribute {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::UpperHex for ArgAttribute {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::ops::BitOr for ArgAttribute {
            type Output = Self;
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            fn bitor(self, other: ArgAttribute) -> Self { self.union(other) }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for ArgAttribute {
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for ArgAttribute {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for ArgAttribute {
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for ArgAttribute {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for ArgAttribute {
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            fn bitand_assign(&mut self, other: Self) {
                *self =
                    Self::from_bits_retain(self.bits()).intersection(other);
            }
        }
        impl ::bitflags::__private::core::ops::Sub for ArgAttribute {
            type Output = Self;
            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for ArgAttribute {
            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for ArgAttribute {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<ArgAttribute> for
            ArgAttribute {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(&mut self, iterator: T) {
                for item in iterator { self.insert(item) }
            }
        }
        impl ::bitflags::__private::core::iter::FromIterator<ArgAttribute> for
            ArgAttribute {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(iterator: T) -> Self {
                use ::bitflags::__private::core::iter::Extend;
                let mut result = Self::empty();
                result.extend(iterator);
                result
            }
        }
        impl ArgAttribute {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[inline]
            pub const fn iter(&self) -> ::bitflags::iter::Iter<ArgAttribute> {
                ::bitflags::iter::Iter::__private_const_new(<ArgAttribute as
                        ::bitflags::Flags>::FLAGS,
                    ArgAttribute::from_bits_retain(self.bits()),
                    ArgAttribute::from_bits_retain(self.bits()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[inline]
            pub const fn iter_names(&self)
                -> ::bitflags::iter::IterNames<ArgAttribute> {
                ::bitflags::iter::IterNames::__private_const_new(<ArgAttribute
                        as ::bitflags::Flags>::FLAGS,
                    ArgAttribute::from_bits_retain(self.bits()),
                    ArgAttribute::from_bits_retain(self.bits()))
            }
        }
        impl ::bitflags::__private::core::iter::IntoIterator for ArgAttribute
            {
            type Item = ArgAttribute;
            type IntoIter = ::bitflags::iter::Iter<ArgAttribute>;
            fn into_iter(self) -> Self::IntoIter { self.iter() }
        }
    };bitflags::bitflags! {
117        impl ArgAttribute: u16 {
118            const CapturesNone     = 0b111;
119            const CapturesAddress  = 0b110;
120            const CapturesReadOnly = 0b100;
121            const NoAlias  = 1 << 3;
122            const NonNull  = 1 << 4;
123            const ReadOnly = 1 << 5;
124            const InReg    = 1 << 6;
125            const NoUndef  = 1 << 7;
126            const Writable = 1 << 8;
127            /// It is UB for this pointer or any pointer derived from it to be used for
128            /// deallocation (except for zero-sized deallocation) while the function is
129            /// executing. Only valid on arguments (including return values that are passed
130            /// indirectly as arguments).
131            const NoFree   = 1 << 9;
132        }
133    }
134    impl ::std::fmt::Debug for ArgAttribute {
    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        ::bitflags::parser::to_writer(self, f)
    }
}rustc_data_structures::external_bitflags_debug! { ArgAttribute }
135}
136
137/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum
138/// defines if this extension should be zero-extension or sign-extension when necessary. When it is
139/// not necessary to extend the argument, this enum is ignored.
140#[derive(#[automatically_derived]
impl ::core::marker::Copy for ArgExtension { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ArgExtension { }
#[automatically_derived]
impl ::core::clone::Clone for ArgExtension {
    #[inline]
    fn clone(&self) -> ArgExtension { *self }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for ArgExtension { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ArgExtension {
    #[inline]
    fn eq(&self, other: &ArgExtension) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ArgExtension {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for ArgExtension {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for ArgExtension {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                ArgExtension::None => "None",
                ArgExtension::Zext => "Zext",
                ArgExtension::Sext => "Sext",
            })
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ArgExtension
            {
            #[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 {
                    ArgExtension::None => {}
                    ArgExtension::Zext => {}
                    ArgExtension::Sext => {}
                }
            }
        }
    };StableHash)]
141pub enum ArgExtension {
142    None,
143    Zext,
144    Sext,
145}
146
147/// A compact representation of LLVM attributes (at least those relevant for this module)
148/// that can be manipulated without interacting with LLVM's Attribute machinery.
149#[derive(#[automatically_derived]
impl ::core::marker::Copy for ArgAttributes { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ArgAttributes { }
#[automatically_derived]
impl ::core::clone::Clone for ArgAttributes {
    #[inline]
    fn clone(&self) -> ArgAttributes {
        let _: ::core::clone::AssertParamIsClone<ArgAttribute>;
        let _: ::core::clone::AssertParamIsClone<ArgExtension>;
        let _: ::core::clone::AssertParamIsClone<Size>;
        let _: ::core::clone::AssertParamIsClone<Option<Align>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for ArgAttributes { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ArgAttributes {
    #[inline]
    fn eq(&self, other: &ArgAttributes) -> bool {
        self.regular == other.regular && self.arg_ext == other.arg_ext &&
                self.pointee_size == other.pointee_size &&
            self.pointee_align == other.pointee_align
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ArgAttributes {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ArgAttribute>;
        let _: ::core::cmp::AssertParamIsEq<ArgExtension>;
        let _: ::core::cmp::AssertParamIsEq<Size>;
        let _: ::core::cmp::AssertParamIsEq<Option<Align>>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for ArgAttributes {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.regular, state);
        ::core::hash::Hash::hash(&self.arg_ext, state);
        ::core::hash::Hash::hash(&self.pointee_size, state);
        ::core::hash::Hash::hash(&self.pointee_align, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for ArgAttributes {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "ArgAttributes",
            "regular", &self.regular, "arg_ext", &self.arg_ext,
            "pointee_size", &self.pointee_size, "pointee_align",
            &&self.pointee_align)
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            ArgAttributes {
            #[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 {
                    ArgAttributes {
                        regular: ref __binding_0,
                        arg_ext: ref __binding_1,
                        pointee_size: ref __binding_2,
                        pointee_align: ref __binding_3 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                        { __binding_3.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
150pub struct ArgAttributes {
151    pub regular: ArgAttribute,
152    pub arg_ext: ArgExtension,
153    /// If the pointer is not null, the minimum dereferenceable size of the pointee, at the time of
154    /// function entry (for arguments) or function return (for return values).
155    pub pointee_size: Size,
156    /// The minimum alignment of the pointee, if any.
157    pub pointee_align: Option<Align>,
158}
159
160impl ArgAttributes {
161    pub fn new() -> Self {
162        ArgAttributes {
163            regular: ArgAttribute::default(),
164            arg_ext: ArgExtension::None,
165            pointee_size: Size::ZERO,
166            pointee_align: None,
167        }
168    }
169
170    pub fn ext(&mut self, ext: ArgExtension) -> &mut Self {
171        if !(self.arg_ext == ArgExtension::None || self.arg_ext == ext) {
    {
        ::core::panicking::panic_fmt(format_args!("cannot set {0:?} when {1:?} is already set",
                ext, self.arg_ext));
    }
};assert!(
172            self.arg_ext == ArgExtension::None || self.arg_ext == ext,
173            "cannot set {:?} when {:?} is already set",
174            ext,
175            self.arg_ext
176        );
177        self.arg_ext = ext;
178        self
179    }
180
181    pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
182        self.regular |= attr;
183        self
184    }
185
186    pub fn contains(&self, attr: ArgAttribute) -> bool {
187        self.regular.contains(attr)
188    }
189
190    /// Checks if these two `ArgAttributes` are equal enough to be considered "the same for all
191    /// function call ABIs".
192    pub fn eq_abi(&self, other: &Self) -> bool {
193        // There's only one regular attribute that matters for the call ABI: InReg.
194        // Everything else is things like noalias, dereferenceable, nonnull, ...
195        // (This also applies to pointee_size, pointee_align.)
196        if self.regular.contains(ArgAttribute::InReg) != other.regular.contains(ArgAttribute::InReg)
197        {
198            return false;
199        }
200        // We also compare the sign extension mode -- this could let the callee make assumptions
201        // about bits that conceptually were not even passed.
202        if self.arg_ext != other.arg_ext {
203            return false;
204        }
205        true
206    }
207}
208
209impl From<ArgAttribute> for ArgAttributes {
210    fn from(value: ArgAttribute) -> Self {
211        Self {
212            regular: value,
213            arg_ext: ArgExtension::None,
214            pointee_size: Size::ZERO,
215            pointee_align: None,
216        }
217    }
218}
219
220/// An argument passed entirely registers with the
221/// same kind (e.g., HFA / HVA on PPC64 and AArch64).
222#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Uniform { }
#[automatically_derived]
impl ::core::clone::Clone for Uniform {
    #[inline]
    fn clone(&self) -> Uniform {
        let _: ::core::clone::AssertParamIsClone<Reg>;
        let _: ::core::clone::AssertParamIsClone<Size>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Uniform { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Uniform { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Uniform {
    #[inline]
    fn eq(&self, other: &Uniform) -> bool {
        self.is_consecutive == other.is_consecutive && self.unit == other.unit
            && self.total == other.total
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Uniform {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Reg>;
        let _: ::core::cmp::AssertParamIsEq<Size>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Uniform {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.unit, state);
        ::core::hash::Hash::hash(&self.total, state);
        ::core::hash::Hash::hash(&self.is_consecutive, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Uniform {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "Uniform",
            "unit", &self.unit, "total", &self.total, "is_consecutive",
            &&self.is_consecutive)
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for Uniform {
            #[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 {
                    Uniform {
                        unit: ref __binding_0,
                        total: ref __binding_1,
                        is_consecutive: ref __binding_2 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
223pub struct Uniform {
224    pub unit: Reg,
225
226    /// The total size of the argument, which can be:
227    /// * equal to `unit.size` (one scalar/vector),
228    /// * a multiple of `unit.size` (an array of scalar/vectors),
229    /// * if `unit.kind` is `Integer`, the last element can be shorter, i.e., `{ i64, i64, i32 }`
230    ///   for 64-bit integers with a total size of 20 bytes. When the argument is actually passed,
231    ///   this size will be rounded up to the nearest multiple of `unit.size`.
232    pub total: Size,
233
234    /// Indicate that the argument is consecutive, in the sense that either all values need to be
235    /// passed in register, or all on the stack. If they are passed on the stack, there should be
236    /// no additional padding between elements.
237    pub is_consecutive: bool,
238}
239
240impl From<Reg> for Uniform {
241    fn from(unit: Reg) -> Uniform {
242        Uniform { unit, total: unit.size, is_consecutive: false }
243    }
244}
245
246impl Uniform {
247    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
248        self.unit.align(cx)
249    }
250
251    /// Pass using one or more values of the given type, without requiring them to be consecutive.
252    /// That is, some values may be passed in register and some on the stack.
253    pub fn new(unit: Reg, total: Size) -> Self {
254        Uniform { unit, total, is_consecutive: false }
255    }
256
257    /// Pass using one or more consecutive values of the given type. Either all values will be
258    /// passed in registers, or all on the stack.
259    pub fn consecutive(unit: Reg, total: Size) -> Self {
260        Uniform { unit, total, is_consecutive: true }
261    }
262}
263
264/// Describes the type used for `PassMode::Cast`.
265///
266/// Passing arguments in this mode works as follows: the registers in the `prefix` (the ones that
267/// are `Some`) get laid out one after the other (using `repr(C)` layout rules). Then the
268/// `rest.unit` register type gets repeated often enough to cover `rest.size`. This describes the
269/// actual type used for the call; the Rust type of the argument is then transmuted to this ABI type
270/// (and all data in the padding between the registers is dropped).
271#[derive(#[automatically_derived]
impl ::core::clone::Clone for CastTarget {
    #[inline]
    fn clone(&self) -> CastTarget {
        CastTarget {
            prefix: ::core::clone::Clone::clone(&self.prefix),
            rest_offset: ::core::clone::Clone::clone(&self.rest_offset),
            rest: ::core::clone::Clone::clone(&self.rest),
            attrs: ::core::clone::Clone::clone(&self.attrs),
        }
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for CastTarget { }
#[automatically_derived]
impl ::core::cmp::PartialEq for CastTarget {
    #[inline]
    fn eq(&self, other: &CastTarget) -> bool {
        self.prefix == other.prefix && self.rest_offset == other.rest_offset
                && self.rest == other.rest && self.attrs == other.attrs
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for CastTarget {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ArrayVec<Reg, 8>>;
        let _: ::core::cmp::AssertParamIsEq<Option<Size>>;
        let _: ::core::cmp::AssertParamIsEq<Uniform>;
        let _: ::core::cmp::AssertParamIsEq<ArgAttributes>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for CastTarget {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.prefix, state);
        ::core::hash::Hash::hash(&self.rest_offset, state);
        ::core::hash::Hash::hash(&self.rest, state);
        ::core::hash::Hash::hash(&self.attrs, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for CastTarget {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "CastTarget",
            "prefix", &self.prefix, "rest_offset", &self.rest_offset, "rest",
            &self.rest, "attrs", &&self.attrs)
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for CastTarget {
            #[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 {
                    CastTarget {
                        prefix: ref __binding_0,
                        rest_offset: ref __binding_1,
                        rest: ref __binding_2,
                        attrs: ref __binding_3 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                        { __binding_3.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
272pub struct CastTarget {
273    // Note that this is fixed to 8 elements for now as ABIs currently don't
274    // need anything further beyond that, and when this code was originally
275    // refactored to use `ArrayVec` it was already using 8, so that stuck
276    // around.
277    pub prefix: ArrayVec<Reg, 8>,
278    /// The offset of `rest` from the start of the value. Currently only implemented for a `Reg`
279    /// pair created by the `offset_pair` method.
280    pub rest_offset: Option<Size>,
281    pub rest: Uniform,
282    pub attrs: ArgAttributes,
283}
284
285impl From<Reg> for CastTarget {
286    fn from(unit: Reg) -> CastTarget {
287        CastTarget::from(Uniform::from(unit))
288    }
289}
290
291impl From<Uniform> for CastTarget {
292    fn from(uniform: Uniform) -> CastTarget {
293        Self::prefixed(Default::default(), uniform)
294    }
295}
296
297impl CastTarget {
298    pub fn prefixed(prefix: ArrayVec<Reg, 8>, rest: Uniform) -> Self {
299        Self { prefix, rest_offset: None, rest, attrs: ArgAttributes::new() }
300    }
301
302    pub fn offset_pair(a: Reg, offset_from_start: Size, b: Reg) -> Self {
303        let mut prefix = ArrayVec::new();
304        prefix.push(a);
305        Self {
306            prefix,
307            rest_offset: Some(offset_from_start),
308            rest: b.into(),
309            attrs: ArgAttributes::new(),
310        }
311    }
312
313    pub fn with_attrs(mut self, attrs: ArgAttributes) -> Self {
314        self.attrs = attrs;
315        self
316    }
317
318    pub fn pair(a: Reg, b: Reg) -> CastTarget {
319        let mut prefix = ArrayVec::new();
320        prefix.push(a);
321        Self::prefixed(prefix, Uniform::from(b))
322    }
323
324    /// When you only access the range containing valid data, you can use this unaligned size;
325    /// otherwise, use the safer `size` method.
326    pub fn unaligned_size<C: HasDataLayout>(&self, _cx: &C) -> Size {
327        // Prefix arguments are passed in specific designated registers
328        let prefix_size = if let Some(offset_from_start) = self.rest_offset {
329            offset_from_start
330        } else {
331            self.prefix.iter().map(|reg| reg.size).fold(Size::ZERO, |acc, size| acc + size)
332        };
333        // Remaining arguments are passed in chunks of the unit size
334        let rest_size =
335            self.rest.unit.size * self.rest.total.bytes().div_ceil(self.rest.unit.size.bytes());
336
337        prefix_size + rest_size
338    }
339
340    pub fn size<C: HasDataLayout>(&self, cx: &C) -> Size {
341        self.unaligned_size(cx).align_to(self.align(cx))
342    }
343
344    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
345        self.prefix
346            .iter()
347            .map(|reg| reg.align(cx))
348            .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), |acc, align| {
349                acc.max(align)
350            })
351    }
352
353    /// Checks if these two `CastTarget` are equal enough to be considered "the same for all
354    /// function call ABIs".
355    pub fn eq_abi(&self, other: &Self) -> bool {
356        let CastTarget {
357            prefix: prefix_l,
358            rest_offset: rest_offset_l,
359            rest: rest_l,
360            attrs: attrs_l,
361        } = self;
362        let CastTarget {
363            prefix: prefix_r,
364            rest_offset: rest_offset_r,
365            rest: rest_r,
366            attrs: attrs_r,
367        } = other;
368        prefix_l == prefix_r
369            && rest_offset_l == rest_offset_r
370            && rest_l == rest_r
371            && attrs_l.eq_abi(attrs_r)
372    }
373}
374
375/// Information about how to pass an argument to,
376/// or return a value from, a function, under some ABI.
377#[derive(#[automatically_derived]
impl<'a, Ty: ::core::clone::Clone> ::core::clone::Clone for ArgAbi<'a, Ty> {
    #[inline]
    fn clone(&self) -> ArgAbi<'a, Ty> {
        ArgAbi {
            layout: ::core::clone::Clone::clone(&self.layout),
            mode: ::core::clone::Clone::clone(&self.mode),
        }
    }
}Clone, #[automatically_derived]
impl<'a, Ty: ::core::cmp::PartialEq> ::core::marker::StructuralPartialEq for
    ArgAbi<'a, Ty> {
}
#[automatically_derived]
impl<'a, Ty: ::core::cmp::PartialEq> ::core::cmp::PartialEq for ArgAbi<'a, Ty>
    {
    #[inline]
    fn eq(&self, other: &ArgAbi<'a, Ty>) -> bool {
        self.layout == other.layout && self.mode == other.mode
    }
}PartialEq, #[automatically_derived]
impl<'a, Ty: ::core::cmp::Eq> ::core::cmp::Eq for ArgAbi<'a, Ty> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<TyAndLayout<'a, Ty>>;
        let _: ::core::cmp::AssertParamIsEq<PassMode>;
    }
}Eq, #[automatically_derived]
impl<'a, Ty: ::core::hash::Hash> ::core::hash::Hash for ArgAbi<'a, Ty> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.layout, state);
        ::core::hash::Hash::hash(&self.mode, state)
    }
}Hash, const _: () =
    {
        impl<'a, Ty> ::rustc_data_structures::stable_hash::StableHash for
            ArgAbi<'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 {
                    ArgAbi { layout: ref __binding_0, mode: ref __binding_1 } =>
                        {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
378pub struct ArgAbi<'a, Ty> {
379    pub layout: TyAndLayout<'a, Ty>,
380    pub mode: PassMode,
381}
382
383// Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl.
384impl<'a, Ty: fmt::Display> fmt::Debug for ArgAbi<'a, Ty> {
385    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386        let ArgAbi { layout, mode } = self;
387        f.debug_struct("ArgAbi").field("layout", layout).field("mode", mode).finish()
388    }
389}
390
391impl<'a, Ty> ArgAbi<'a, Ty> {
392    /// This defines the "default ABI" for that type, that is then later adjusted in `fn_abi_adjust_for_abi`.
393    pub fn new(
394        layout: TyAndLayout<'a, Ty>,
395        scalar_attrs: impl Fn(Scalar, Size) -> ArgAttributes,
396    ) -> Self {
397        let mode = match layout.backend_repr {
398            _ if layout.is_zst() => PassMode::Ignore,
399            BackendRepr::Scalar(scalar) => PassMode::Direct(scalar_attrs(scalar, Size::ZERO)),
400            BackendRepr::ScalarPair { a, b, b_offset } => {
401                PassMode::Pair(scalar_attrs(a, Size::ZERO), scalar_attrs(b, b_offset))
402            }
403            BackendRepr::SimdVector { .. } => PassMode::Direct(ArgAttributes::new()),
404            BackendRepr::Memory { .. } => Self::indirect_pass_mode(&layout),
405            BackendRepr::SimdScalableVector { .. } => PassMode::Direct(ArgAttributes::new()),
406        };
407        ArgAbi { layout, mode }
408    }
409
410    fn indirect_pass_mode(layout: &TyAndLayout<'a, Ty>) -> PassMode {
411        let mut attrs = ArgAttributes::new();
412
413        // For non-immediate arguments the callee gets its own copy of
414        // the value on the stack, so there are no aliases. The function
415        // can capture the address of the argument, but not the provenance.
416        attrs
417            .set(ArgAttribute::NoAlias)
418            .set(ArgAttribute::CapturesAddress)
419            .set(ArgAttribute::NonNull)
420            .set(ArgAttribute::NoUndef)
421            .set(ArgAttribute::NoFree);
422        attrs.pointee_size = layout.size;
423        attrs.pointee_align = Some(layout.align.abi);
424
425        let meta_attrs = layout.is_unsized().then_some(ArgAttributes::new());
426
427        PassMode::Indirect { attrs, meta_attrs, on_stack: false }
428    }
429
430    /// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead.
431    /// This is valid for both sized and unsized arguments.
432    #[track_caller]
433    pub fn make_indirect(&mut self) {
434        match self.mode {
435            PassMode::Direct(_) | PassMode::Pair(_, _) => {
436                self.mode = Self::indirect_pass_mode(&self.layout);
437            }
438            PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
439                // already indirect
440            }
441            _ => {
    ::core::panicking::panic_fmt(format_args!("Tried to make {0:?} indirect",
            self.mode));
}panic!("Tried to make {:?} indirect", self.mode),
442        }
443    }
444
445    /// Same as `make_indirect`, but for arguments that are ignored. Only needed for ABIs that pass
446    /// ZSTs indirectly.
447    #[track_caller]
448    pub fn make_indirect_from_ignore(&mut self) {
449        match self.mode {
450            PassMode::Ignore => {
451                self.mode = Self::indirect_pass_mode(&self.layout);
452            }
453            PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
454                // already indirect
455            }
456            _ => {
    ::core::panicking::panic_fmt(format_args!("Tried to make {0:?} indirect (expected `PassMode::Ignore`)",
            self.mode));
}panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode),
457        }
458    }
459
460    /// Pass this argument indirectly, by placing it at a fixed stack offset.
461    /// This corresponds to the `byval` LLVM argument attribute.
462    /// This is only valid for sized arguments.
463    ///
464    /// `byval_align` specifies the alignment of the `byval` stack slot, which does not need to
465    /// correspond to the type's alignment. This will be `Some` if the target's ABI specifies that
466    /// stack slots used for arguments passed by-value have specific alignment requirements which
467    /// differ from the alignment used in other situations.
468    ///
469    /// If `None`, the type's alignment is used.
470    ///
471    /// If the resulting alignment differs from the type's alignment,
472    /// the argument will be copied to an alloca with sufficient alignment,
473    /// either in the caller (if the type's alignment is lower than the byval alignment)
474    /// or in the callee (if the type's alignment is higher than the byval alignment),
475    /// to ensure that Rust code never sees an underaligned pointer.
476    pub fn pass_by_stack_offset(&mut self, byval_align: Option<Align>) {
477        if !!self.layout.is_unsized() {
    {
        ::core::panicking::panic_fmt(format_args!("used byval ABI for unsized layout"));
    }
};assert!(!self.layout.is_unsized(), "used byval ABI for unsized layout");
478        self.make_indirect();
479        match self.mode {
480            PassMode::Indirect { ref mut attrs, meta_attrs: _, ref mut on_stack } => {
481                *on_stack = true;
482
483                // Some platforms, like 32-bit x86, change the alignment of the type when passing
484                // `byval`. Account for that.
485                if let Some(byval_align) = byval_align {
486                    // On all targets with byval align this is currently true, so let's assert it.
487                    if true {
    if !(byval_align >= Align::from_bytes(4).unwrap()) {
        ::core::panicking::panic("assertion failed: byval_align >= Align::from_bytes(4).unwrap()")
    };
};debug_assert!(byval_align >= Align::from_bytes(4).unwrap());
488                    attrs.pointee_align = Some(byval_align);
489                }
490            }
491            _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
492        }
493    }
494
495    pub fn extend_integer_width_to(&mut self, bits: u64) {
496        // Only integers have signedness
497        if let BackendRepr::Scalar(scalar) = self.layout.backend_repr
498            && let Primitive::Int(i, signed) = scalar.primitive()
499            && i.size().bits() < bits
500            && let PassMode::Direct(ref mut attrs) = self.mode
501        {
502            if signed {
503                attrs.ext(ArgExtension::Sext)
504            } else {
505                attrs.ext(ArgExtension::Zext)
506            };
507        }
508    }
509
510    pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
511        self.mode = PassMode::Cast { cast: Box::new(target.into()), pad_i32_count: 0 };
512    }
513
514    pub fn cast_to_with_attrs<T: Into<CastTarget>>(&mut self, target: T, attrs: ArgAttributes) {
515        self.mode =
516            PassMode::Cast { cast: Box::new(target.into().with_attrs(attrs)), pad_i32_count: 0 };
517    }
518
519    /// Cast to `target`, forwarding `NoUndef` only when the layout provably has no uninit
520    /// bytes *and* the cast exactly covers the layout (`target.size(cx) == self.layout.size`).
521    /// A wider cast (e.g. `Uniform::new` rounding a 3-byte aggregate up to an `i32`) covers
522    /// undef padding bytes that must not be marked `noundef`; a narrower cast does not occur,
523    /// since a `PassMode::Cast` target always covers the whole value.
524    pub fn cast_to_maybe_noundef<T, C>(&mut self, target: T, cx: &C)
525    where
526        T: Into<CastTarget>,
527        Ty: TyAbiInterface<'a, C> + Copy,
528        C: HasDataLayout,
529    {
530        let target = target.into();
531        let attr = if layout_is_noundef(self.layout, cx) && target.size(cx) == self.layout.size {
532            ArgAttribute::NoUndef
533        } else {
534            ArgAttribute::default()
535        };
536        self.cast_to_with_attrs(target, attr.into());
537    }
538
539    pub fn cast_to_and_pad_i32<T: Into<CastTarget>>(&mut self, target: T, pad_i32_count: u8) {
540        self.mode = PassMode::Cast { cast: Box::new(target.into()), pad_i32_count };
541    }
542
543    pub fn is_indirect(&self) -> bool {
544        #[allow(non_exhaustive_omitted_patterns)] match self.mode {
    PassMode::Indirect { .. } => true,
    _ => false,
}matches!(self.mode, PassMode::Indirect { .. })
545    }
546
547    pub fn is_sized_indirect(&self) -> bool {
548        #[allow(non_exhaustive_omitted_patterns)] match self.mode {
    PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => true,
    _ => false,
}matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ })
549    }
550
551    pub fn is_unsized_indirect(&self) -> bool {
552        #[allow(non_exhaustive_omitted_patterns)] match self.mode {
    PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => true,
    _ => false,
}matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ })
553    }
554
555    pub fn is_ignore(&self) -> bool {
556        #[allow(non_exhaustive_omitted_patterns)] match self.mode {
    PassMode::Ignore => true,
    _ => false,
}matches!(self.mode, PassMode::Ignore)
557    }
558
559    /// Checks if these two `ArgAbi` are equal enough to be considered "the same for all
560    /// function call ABIs".
561    pub fn eq_abi(&self, other: &Self) -> bool
562    where
563        Ty: PartialEq,
564    {
565        // Ideally we'd just compare the `mode`, but that is not enough -- for some modes LLVM will look
566        // at the type.
567        self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode) && {
568            // `fn_arg_sanity_check` accepts `PassMode::Direct` for some aggregates.
569            // That elevates any type difference to an ABI difference since we just use the
570            // full Rust type as the LLVM argument/return type.
571            if #[allow(non_exhaustive_omitted_patterns)] match self.mode {
    PassMode::Direct(..) => true,
    _ => false,
}matches!(self.mode, PassMode::Direct(..))
572                && #[allow(non_exhaustive_omitted_patterns)] match self.layout.backend_repr {
    BackendRepr::Memory { .. } => true,
    _ => false,
}matches!(self.layout.backend_repr, BackendRepr::Memory { .. })
573            {
574                // For aggregates in `Direct` mode to be compatible, the types need to be equal.
575                self.layout.ty == other.layout.ty
576            } else {
577                true
578            }
579        }
580    }
581}
582
583#[derive(#[automatically_derived]
impl ::core::marker::Copy for RiscvInterruptKind { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for RiscvInterruptKind { }
#[automatically_derived]
impl ::core::clone::Clone for RiscvInterruptKind {
    #[inline]
    fn clone(&self) -> RiscvInterruptKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for RiscvInterruptKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for RiscvInterruptKind {
    #[inline]
    fn eq(&self, other: &RiscvInterruptKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RiscvInterruptKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for RiscvInterruptKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for RiscvInterruptKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                RiscvInterruptKind::Machine => "Machine",
                RiscvInterruptKind::Supervisor => "Supervisor",
            })
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            RiscvInterruptKind {
            #[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 {
                    RiscvInterruptKind::Machine => {}
                    RiscvInterruptKind::Supervisor => {}
                }
            }
        }
    };StableHash)]
584pub enum RiscvInterruptKind {
585    Machine,
586    Supervisor,
587}
588
589impl RiscvInterruptKind {
590    pub fn as_str(&self) -> &'static str {
591        match self {
592            Self::Machine => "machine",
593            Self::Supervisor => "supervisor",
594        }
595    }
596}
597
598/// Metadata describing how the arguments to a native function
599/// should be passed in order to respect the native ABI.
600///
601/// The signature represented by this type may not match the MIR function signature.
602/// Certain attributes, like `#[track_caller]` can introduce additional arguments, which are present in [`FnAbi`], but not in `FnSig`.
603/// The std::offload module also adds an addition dyn_ptr argument to the GpuKernel ABI.
604/// While this difference is rarely relevant, it should still be kept in mind.
605///
606/// I will do my best to describe this structure, but these
607/// comments are reverse-engineered and may be inaccurate. -NDM
608#[derive(#[automatically_derived]
impl<'a, Ty: ::core::clone::Clone> ::core::clone::Clone for FnAbi<'a, Ty> {
    #[inline]
    fn clone(&self) -> FnAbi<'a, Ty> {
        FnAbi {
            args: ::core::clone::Clone::clone(&self.args),
            ret: ::core::clone::Clone::clone(&self.ret),
            c_variadic: ::core::clone::Clone::clone(&self.c_variadic),
            fixed_count: ::core::clone::Clone::clone(&self.fixed_count),
            conv: ::core::clone::Clone::clone(&self.conv),
            can_unwind: ::core::clone::Clone::clone(&self.can_unwind),
        }
    }
}Clone, #[automatically_derived]
impl<'a, Ty: ::core::cmp::PartialEq> ::core::marker::StructuralPartialEq for
    FnAbi<'a, Ty> {
}
#[automatically_derived]
impl<'a, Ty: ::core::cmp::PartialEq> ::core::cmp::PartialEq for FnAbi<'a, Ty>
    {
    #[inline]
    fn eq(&self, other: &FnAbi<'a, Ty>) -> bool {
        self.c_variadic == other.c_variadic &&
                            self.fixed_count == other.fixed_count &&
                        self.can_unwind == other.can_unwind &&
                    self.args == other.args && self.ret == other.ret &&
            self.conv == other.conv
    }
}PartialEq, #[automatically_derived]
impl<'a, Ty: ::core::cmp::Eq> ::core::cmp::Eq for FnAbi<'a, Ty> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Box<[ArgAbi<'a, Ty>]>>;
        let _: ::core::cmp::AssertParamIsEq<ArgAbi<'a, Ty>>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<u32>;
        let _: ::core::cmp::AssertParamIsEq<CanonAbi>;
    }
}Eq, #[automatically_derived]
impl<'a, Ty: ::core::hash::Hash> ::core::hash::Hash for FnAbi<'a, Ty> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.args, state);
        ::core::hash::Hash::hash(&self.ret, state);
        ::core::hash::Hash::hash(&self.c_variadic, state);
        ::core::hash::Hash::hash(&self.fixed_count, state);
        ::core::hash::Hash::hash(&self.conv, state);
        ::core::hash::Hash::hash(&self.can_unwind, state)
    }
}Hash, const _: () =
    {
        impl<'a, Ty> ::rustc_data_structures::stable_hash::StableHash for
            FnAbi<'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 {
                    FnAbi {
                        args: ref __binding_0,
                        ret: ref __binding_1,
                        c_variadic: ref __binding_2,
                        fixed_count: ref __binding_3,
                        conv: ref __binding_4,
                        can_unwind: ref __binding_5 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                        { __binding_3.stable_hash(__hcx, __hasher); }
                        { __binding_4.stable_hash(__hcx, __hasher); }
                        { __binding_5.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
609pub struct FnAbi<'a, Ty> {
610    /// The type, layout, and information about how each argument is passed.
611    pub args: Box<[ArgAbi<'a, Ty>]>,
612
613    /// The layout, type, and the way a value is returned from this function.
614    pub ret: ArgAbi<'a, Ty>,
615
616    /// Marks this function as variadic (accepting a variable number of arguments).
617    pub c_variadic: bool,
618
619    /// The count of non-variadic arguments.
620    ///
621    /// Should only be different from args.len() when c_variadic is true.
622    /// This can be used to know whether an argument is variadic or not.
623    pub fixed_count: u32,
624    /// The calling convention of this function.
625    pub conv: CanonAbi,
626    /// Indicates if an unwind may happen across a call to this function.
627    pub can_unwind: bool,
628}
629
630// Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl.
631impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> {
632    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
633        let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind } = self;
634        f.debug_struct("FnAbi")
635            .field("args", args)
636            .field("ret", ret)
637            .field("c_variadic", c_variadic)
638            .field("fixed_count", fixed_count)
639            .field("conv", conv)
640            .field("can_unwind", can_unwind)
641            .finish()
642    }
643}
644
645impl<'a, Ty> FnAbi<'a, Ty> {
646    pub fn adjust_for_foreign_abi<C>(&mut self, cx: &C, abi: ExternAbi)
647    where
648        Ty: TyAbiInterface<'a, C> + Copy,
649        C: HasDataLayout + HasTargetSpec + HasX86AbiOpt,
650    {
651        if abi == ExternAbi::X86Interrupt {
652            if let Some(arg) = self.args.first_mut() {
653                arg.pass_by_stack_offset(None);
654            }
655            return;
656        }
657
658        let spec = cx.target_spec();
659        match &spec.arch {
660            Arch::X86 => {
661                let (flavor, regparm) = match abi {
662                    ExternAbi::Fastcall { .. } | ExternAbi::Vectorcall { .. } => {
663                        (x86::Flavor::FastcallOrVectorcall, None)
664                    }
665                    ExternAbi::C { .. } | ExternAbi::Cdecl { .. } | ExternAbi::Stdcall { .. } => {
666                        (x86::Flavor::General, cx.x86_abi_opt().regparm)
667                    }
668                    _ => (x86::Flavor::General, None),
669                };
670                let reg_struct_return = cx.x86_abi_opt().reg_struct_return;
671                let opts = x86::X86Options { flavor, regparm, reg_struct_return };
672                if spec.is_like_msvc {
673                    x86_win32::compute_abi_info(cx, self, opts);
674                } else {
675                    x86::compute_abi_info(cx, self, opts);
676                }
677            }
678            Arch::X86_64 => match abi {
679                ExternAbi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
680                ExternAbi::Win64 { .. } | ExternAbi::Vectorcall { .. } => {
681                    x86_win64::compute_abi_info(cx, self)
682                }
683                _ => {
684                    if cx.target_spec().is_like_windows {
685                        x86_win64::compute_abi_info(cx, self)
686                    } else {
687                        x86_64::compute_abi_info(cx, self)
688                    }
689                }
690            },
691            Arch::AArch64 | Arch::Arm64EC => {
692                let kind = if cx.target_spec().is_like_darwin {
693                    aarch64::AbiKind::DarwinPCS
694                } else if cx.target_spec().is_like_windows {
695                    aarch64::AbiKind::Win64
696                } else {
697                    aarch64::AbiKind::AAPCS
698                };
699                aarch64::compute_abi_info(cx, self, kind)
700            }
701            Arch::AmdGpu => amdgpu::compute_abi_info(cx, self),
702            Arch::Arm => arm::compute_abi_info(cx, self),
703            Arch::Avr => avr::compute_abi_info(cx, self),
704            Arch::LoongArch32 | Arch::LoongArch64 => loongarch::compute_abi_info(cx, self),
705            Arch::M68k => m68k::compute_abi_info(cx, self),
706            Arch::CSky => csky::compute_abi_info(cx, self),
707            Arch::Mips | Arch::Mips32r6 => mips::compute_abi_info(cx, self),
708            Arch::Mips64 | Arch::Mips64r6 => mips64::compute_abi_info(cx, self),
709            Arch::PowerPC => powerpc::compute_abi_info(cx, self),
710            Arch::PowerPC64 => powerpc64::compute_abi_info(cx, self),
711            Arch::S390x => s390x::compute_abi_info(cx, self),
712            Arch::Msp430 => msp430::compute_abi_info(cx, self),
713            Arch::Sparc => sparc::compute_abi_info(cx, self),
714            Arch::Sparc64 => sparc64::compute_abi_info(cx, self),
715            Arch::Nvptx64 => {
716                if abi == ExternAbi::PtxKernel || abi == ExternAbi::GpuKernel {
717                    nvptx64::compute_ptx_kernel_abi_info(cx, self)
718                } else {
719                    nvptx64::compute_abi_info(cx, self)
720                }
721            }
722            Arch::Hexagon => hexagon::compute_abi_info(cx, self),
723            Arch::Xtensa => xtensa::compute_abi_info(cx, self),
724            Arch::RiscV32 | Arch::RiscV64 => riscv::compute_abi_info(cx, self),
725            Arch::Wasm32 | Arch::Wasm64 => wasm::compute_abi_info(cx, self),
726            Arch::Bpf => bpf::compute_abi_info(cx, self),
727            arch @ (Arch::SpirV | Arch::Other(_)) => {
728                {
    ::core::panicking::panic_fmt(format_args!("no lowering implemented for {0}",
            arch));
}panic!("no lowering implemented for {arch}")
729            }
730        }
731    }
732
733    pub fn adjust_for_rust_abi<C>(&mut self, cx: &C)
734    where
735        Ty: TyAbiInterface<'a, C> + Copy,
736        C: HasDataLayout + HasTargetSpec,
737    {
738        let spec = cx.target_spec();
739        match &spec.arch {
740            Arch::X86 => x86::compute_rust_abi_info(cx, self),
741            Arch::RiscV32 | Arch::RiscV64 => riscv::compute_rust_abi_info(cx, self),
742            Arch::LoongArch32 | Arch::LoongArch64 => loongarch::compute_rust_abi_info(cx, self),
743            Arch::AArch64 => aarch64::compute_rust_abi_info(cx, self),
744            Arch::Bpf => bpf::compute_rust_abi_info(self),
745            _ => {}
746        };
747
748        for (arg_idx, arg) in self
749            .args
750            .iter_mut()
751            .enumerate()
752            .map(|(idx, arg)| (Some(idx), arg))
753            .chain(iter::once((None, &mut self.ret)))
754        {
755            // If the logic above already picked a specific type to cast the argument to, leave that
756            // in place.
757            if #[allow(non_exhaustive_omitted_patterns)] match arg.mode {
    PassMode::Ignore | PassMode::Cast { .. } => true,
    _ => false,
}matches!(arg.mode, PassMode::Ignore | PassMode::Cast { .. }) {
758                continue;
759            }
760
761            // Always extend `bool` in the Rust ABI
762            let extend_bool = |attrs: &mut ArgAttributes, scalar: Scalar| {
763                if scalar.is_bool() {
764                    attrs.ext(ArgExtension::Zext);
765                }
766            };
767
768            if let PassMode::Direct(attrs) = &mut arg.mode
769                && let BackendRepr::Scalar(scalar) = arg.layout.backend_repr
770            {
771                extend_bool(attrs, scalar);
772            } else if let PassMode::Pair(a_attrs, b_attrs) = &mut arg.mode
773                && let BackendRepr::ScalarPair { a, b, b_offset: _ } = arg.layout.backend_repr
774            {
775                extend_bool(a_attrs, a);
776                extend_bool(b_attrs, b);
777            }
778
779            if arg_idx.is_none()
780                && arg.layout.size > Primitive::Pointer(AddressSpace::ZERO).size(cx) * 2
781                && !#[allow(non_exhaustive_omitted_patterns)] match arg.layout.backend_repr {
    BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } =>
        true,
    _ => false,
}matches!(
782                    arg.layout.backend_repr,
783                    BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. }
784                )
785            {
786                // Return values larger than 2 registers using a return area
787                // pointer. LLVM and Cranelift disagree about how to return
788                // values that don't fit in the registers designated for return
789                // values. LLVM will force the entire return value to be passed
790                // by return area pointer, while Cranelift will look at each IR level
791                // return value independently and decide to pass it in a
792                // register or not, which would result in the return value
793                // being passed partially in registers and partially through a
794                // return area pointer. For large IR-level values such as `i128`,
795                // cranelift will even split up the value into smaller chunks.
796                //
797                // While Cranelift may need to be fixed as the LLVM behavior is
798                // generally more correct with respect to the surface language,
799                // forcing this behavior in rustc itself makes it easier for
800                // other backends to conform to the Rust ABI and for the C ABI
801                // rustc already handles this behavior anyway.
802                //
803                // In addition LLVM's decision to pass the return value in
804                // registers or using a return area pointer depends on how
805                // exactly the return type is lowered to an LLVM IR type. For
806                // example `Option<u128>` can be lowered as `{ i128, i128 }`
807                // in which case the x86_64 backend would use a return area
808                // pointer, or it could be passed as `{ i32, i128 }` in which
809                // case the x86_64 backend would pass it in registers by taking
810                // advantage of an LLVM ABI extension that allows using 3
811                // registers for the x86_64 sysv call conv rather than the
812                // officially specified 2 registers.
813                //
814                // FIXME: Technically we should look at the amount of available
815                // return registers rather than guessing that there are 2
816                // registers for return values. In practice only a couple of
817                // architectures have less than 2 return registers. None of
818                // which supported by Cranelift.
819                //
820                // NOTE: This adjustment is only necessary for the Rust ABI as
821                // for other ABI's the calling convention implementations in
822                // rustc_target already ensure any return value which doesn't
823                // fit in the available amount of return registers is passed in
824                // the right way for the current target.
825                //
826                // The adjustment is not necessary nor desired for types with a vector
827                // representation; those are handled below.
828                arg.make_indirect();
829                continue;
830            }
831
832            match arg.layout.backend_repr {
833                BackendRepr::Memory { .. } => {
834                    // Compute `Aggregate` ABI.
835
836                    let is_indirect_not_on_stack =
837                        #[allow(non_exhaustive_omitted_patterns)] match arg.mode {
    PassMode::Indirect { on_stack: false, .. } => true,
    _ => false,
}matches!(arg.mode, PassMode::Indirect { on_stack: false, .. });
838                    if !is_indirect_not_on_stack {
    ::core::panicking::panic("assertion failed: is_indirect_not_on_stack")
};assert!(is_indirect_not_on_stack);
839
840                    let size = arg.layout.size;
841                    if arg.layout.is_sized()
842                        && size <= Primitive::Pointer(AddressSpace::ZERO).size(cx)
843                    {
844                        // We want to pass small aggregates as immediates, but using
845                        // an LLVM aggregate type for this leads to bad optimizations,
846                        // so we pick an appropriately sized integer type instead.
847                        arg.cast_to_maybe_noundef(Reg { kind: RegKind::Integer, size }, cx);
848                    } else if self.conv == CanonAbi::RustTail {
849                        if !arg.layout.is_sized() {
    {
        ::core::panicking::panic_fmt(format_args!("extern \"tail\" arguments must be sized"));
    }
};assert!(arg.layout.is_sized(), "extern \"tail\" arguments must be sized");
850                        arg.pass_by_stack_offset(None);
851                    }
852                }
853
854                BackendRepr::SimdVector { .. } => {
855                    // This is a fun case! The gist of what this is doing is
856                    // that we want callers and callees to always agree on the
857                    // ABI of how they pass SIMD arguments. If we were to *not*
858                    // make these arguments indirect then they'd be immediates
859                    // in LLVM, which means that they'd used whatever the
860                    // appropriate ABI is for the callee and the caller. That
861                    // means, for example, if the caller doesn't have AVX
862                    // enabled but the callee does, then passing an AVX argument
863                    // across this boundary would cause corrupt data to show up.
864                    //
865                    // This problem is fixed by unconditionally passing SIMD
866                    // arguments through memory between callers and callees
867                    // which should get them all to agree on ABI regardless of
868                    // target feature sets. Some more information about this
869                    // issue can be found in #44367.
870                    //
871                    // We *could* do better in some cases, e.g. on x86_64 targets where SSE2 is
872                    // required. However, it turns out that that makes LLVM worse at optimizing this
873                    // code, so we pass things indirectly even there. See #139029 for more on that.
874                    if spec.simd_types_indirect {
875                        arg.make_indirect();
876                    }
877                }
878
879                _ => {}
880            }
881        }
882    }
883}
884
885/// Determines whether `layout` contains no uninit bytes (no padding, no unions),
886/// using only the computed layout.
887///
888/// Conservative: returns `false` for anything it cannot prove fully initialized,
889/// including multi-variant enums and SIMD vectors.
890// FIXME: extend to multi-variant enums (per-variant padding analysis needed).
891fn layout_is_noundef<'a, Ty, C>(layout: TyAndLayout<'a, Ty>, cx: &C) -> bool
892where
893    Ty: TyAbiInterface<'a, C> + Copy,
894    C: HasDataLayout,
895{
896    match layout.backend_repr {
897        BackendRepr::Scalar(scalar) => !scalar.is_uninit_valid(),
898        BackendRepr::ScalarPair { a: s1, b: s2, b_offset: _ } => {
899            !s1.is_uninit_valid()
900                && !s2.is_uninit_valid()
901                // Ensure there is no padding.
902                && s1.size(cx) + s2.size(cx) == layout.size
903        }
904        BackendRepr::Memory { .. } => match layout.fields {
905            FieldsShape::Primitive | FieldsShape::Union(_) => false,
906            // Array elements are at stride offsets with no inter-element gaps.
907            FieldsShape::Array { stride: _, count } => {
908                count == 0 || layout_is_noundef(layout.field(cx, 0), cx)
909            }
910            FieldsShape::Arbitrary { .. } => {
911                // With `Variants::Multiple`, `layout.fields` only covers shared
912                // bytes (niche/discriminant); per-variant data is absent, so
913                // full coverage cannot be proven.
914                #[allow(non_exhaustive_omitted_patterns)] match layout.variants {
    Variants::Single { .. } => true,
    _ => false,
}matches!(layout.variants, Variants::Single { .. }) && fields_are_noundef(layout, cx)
915            }
916        },
917        BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } => false,
918    }
919}
920
921/// Returns `true` if the fields of `layout` contiguously cover bytes `0..layout.size`
922/// with no padding gaps and each field is recursively `layout_is_noundef`.
923fn fields_are_noundef<'a, Ty, C>(layout: TyAndLayout<'a, Ty>, cx: &C) -> bool
924where
925    Ty: TyAbiInterface<'a, C> + Copy,
926    C: HasDataLayout,
927{
928    let mut cursor = Size::ZERO;
929    for i in layout.fields.index_by_increasing_offset() {
930        let field = layout.field(cx, i);
931        if field.size == Size::ZERO {
932            continue;
933        }
934        if layout.fields.offset(i) != cursor {
935            return false;
936        }
937        if !layout_is_noundef(field, cx) {
938            return false;
939        }
940        cursor += field.size;
941    }
942    cursor == layout.size
943}
944
945// Some types are used a lot. Make sure they don't unintentionally get bigger.
946#[cfg(target_pointer_width = "64")]
947mod size_asserts {
948    use rustc_data_structures::static_assert_size;
949
950    use super::*;
951    // tidy-alphabetical-start
952    const _: [(); 56] = [(); ::std::mem::size_of::<ArgAbi<'_, usize>>()];static_assert_size!(ArgAbi<'_, usize>, 56);
953    const _: [(); 80] = [(); ::std::mem::size_of::<FnAbi<'_, usize>>()];static_assert_size!(FnAbi<'_, usize>, 80);
954    // tidy-alphabetical-end
955}