Skip to main content

rustc_public/mir/
alloc.rs

1//! This module provides methods to retrieve allocation information, such as static variables.
2
3use std::io::Read;
4
5use serde::Serialize;
6
7use crate::mir::mono::{Instance, StaticDef};
8use crate::target::{Endian, MachineInfo};
9use crate::ty::{Allocation, Binder, ExistentialTraitRef, Ty, index_impl};
10use crate::{Error, ThreadLocalIndex, with};
11
12/// An allocation in the rustc_public's IR global memory can be either a function pointer,
13/// a static, or a "real" allocation with some data in it.
14#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GlobalAlloc {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            GlobalAlloc::Function(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Function", &__self_0),
            GlobalAlloc::VTable(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "VTable",
                    __self_0, &__self_1),
            GlobalAlloc::Static(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Static",
                    &__self_0),
            GlobalAlloc::Memory(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Memory",
                    &__self_0),
            GlobalAlloc::TypeId { ty: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "TypeId", "ty", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GlobalAlloc {
    #[inline]
    fn clone(&self) -> GlobalAlloc {
        match self {
            GlobalAlloc::Function(__self_0) =>
                GlobalAlloc::Function(::core::clone::Clone::clone(__self_0)),
            GlobalAlloc::VTable(__self_0, __self_1) =>
                GlobalAlloc::VTable(::core::clone::Clone::clone(__self_0),
                    ::core::clone::Clone::clone(__self_1)),
            GlobalAlloc::Static(__self_0) =>
                GlobalAlloc::Static(::core::clone::Clone::clone(__self_0)),
            GlobalAlloc::Memory(__self_0) =>
                GlobalAlloc::Memory(::core::clone::Clone::clone(__self_0)),
            GlobalAlloc::TypeId { ty: __self_0 } =>
                GlobalAlloc::TypeId {
                    ty: ::core::clone::Clone::clone(__self_0),
                },
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for GlobalAlloc {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Instance>;
        let _: ::core::cmp::AssertParamIsEq<Ty>;
        let _:
                ::core::cmp::AssertParamIsEq<Option<Binder<ExistentialTraitRef>>>;
        let _: ::core::cmp::AssertParamIsEq<StaticDef>;
        let _: ::core::cmp::AssertParamIsEq<Allocation>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for GlobalAlloc {
    #[inline]
    fn eq(&self, other: &GlobalAlloc) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (GlobalAlloc::Function(__self_0),
                    GlobalAlloc::Function(__arg1_0)) => __self_0 == __arg1_0,
                (GlobalAlloc::VTable(__self_0, __self_1),
                    GlobalAlloc::VTable(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (GlobalAlloc::Static(__self_0), GlobalAlloc::Static(__arg1_0))
                    => __self_0 == __arg1_0,
                (GlobalAlloc::Memory(__self_0), GlobalAlloc::Memory(__arg1_0))
                    => __self_0 == __arg1_0,
                (GlobalAlloc::TypeId { ty: __self_0 }, GlobalAlloc::TypeId {
                    ty: __arg1_0 }) => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl _serde::Serialize for GlobalAlloc {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                match *self {
                    GlobalAlloc::Function(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "GlobalAlloc", 0u32, "Function", __field0),
                    GlobalAlloc::VTable(ref __field0, ref __field1) => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_tuple_variant(__serializer,
                                    "GlobalAlloc", 1u32, "VTable", 0 + 1 + 1)?;
                        _serde::ser::SerializeTupleVariant::serialize_field(&mut __serde_state,
                                __field0)?;
                        _serde::ser::SerializeTupleVariant::serialize_field(&mut __serde_state,
                                __field1)?;
                        _serde::ser::SerializeTupleVariant::end(__serde_state)
                    }
                    GlobalAlloc::Static(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "GlobalAlloc", 2u32, "Static", __field0),
                    GlobalAlloc::Memory(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "GlobalAlloc", 3u32, "Memory", __field0),
                    GlobalAlloc::TypeId { ref ty } => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_struct_variant(__serializer,
                                    "GlobalAlloc", 4u32, "TypeId", 0 + 1)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "ty", ty)?;
                        _serde::ser::SerializeStructVariant::end(__serde_state)
                    }
                }
            }
        }
    };Serialize)]
15pub enum GlobalAlloc {
16    /// The alloc ID is used as a function pointer.
17    Function(Instance),
18    /// This alloc ID points to a symbolic (not-reified) vtable.
19    /// The `None` trait ref is used to represent auto traits.
20    VTable(Ty, Option<Binder<ExistentialTraitRef>>),
21    /// The alloc ID points to a "lazy" static variable that did not get computed (yet).
22    /// This is also used to break the cycle in recursive statics.
23    Static(StaticDef),
24    /// The alloc ID points to memory.
25    Memory(Allocation),
26    /// The first pointer-sized segment of a type id. On 64 bit systems, the 128 bit type id
27    /// is split into two segments, on 32 bit systems there are 4 segments, and so on.
28    TypeId { ty: Ty },
29}
30
31impl From<AllocId> for GlobalAlloc {
32    fn from(value: AllocId) -> Self {
33        with(|cx| cx.global_alloc(value))
34    }
35}
36
37impl GlobalAlloc {
38    /// Retrieve the allocation id for a global allocation if it exists.
39    ///
40    /// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given
41    /// type for the optional trait if the type implements the trait.
42    ///
43    /// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`.
44    pub fn vtable_allocation(&self) -> Option<AllocId> {
45        with(|cx| cx.vtable_allocation(self))
46    }
47}
48
49/// A unique identification number for each provenance
50#[derive(#[automatically_derived]
impl ::core::clone::Clone for AllocId {
    #[inline]
    fn clone(&self) -> AllocId {
        let _: ::core::clone::AssertParamIsClone<usize>;
        let _: ::core::clone::AssertParamIsClone<ThreadLocalIndex>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AllocId { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for AllocId {
    #[inline]
    fn eq(&self, other: &AllocId) -> bool {
        self.0 == other.0 && self.1 == other.1
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for AllocId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<usize>;
        let _: ::core::cmp::AssertParamIsEq<ThreadLocalIndex>;
    }
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for AllocId {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field2_finish(f, "AllocId",
            &self.0, &&self.1)
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for AllocId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state);
        ::core::hash::Hash::hash(&self.1, state)
    }
}Hash)]
51pub struct AllocId(usize, ThreadLocalIndex);
52impl crate::IndexedVal for AllocId {
    fn to_val(index: usize) -> Self {
        AllocId(index, crate::ThreadLocalIndex)
    }
    fn to_index(&self) -> usize { self.0 }
}
impl ::serde::Serialize for AllocId {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
        S: ::serde::Serializer {
        let n: usize = self.0;
        ::serde::Serialize::serialize(&n, serializer)
    }
}index_impl!(AllocId);
53
54/// Utility function used to read an allocation data into a unassigned integer.
55pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
56    let mut buf = [0u8; size_of::<u128>()];
57    match MachineInfo::target_endianness() {
58        Endian::Little => {
59            bytes.read_exact(&mut buf[..bytes.len()])?;
60            Ok(u128::from_le_bytes(buf))
61        }
62        Endian::Big => {
63            bytes.read_exact(&mut buf[16 - bytes.len()..])?;
64            Ok(u128::from_be_bytes(buf))
65        }
66    }
67}
68
69/// Utility function used to read an allocation data into an assigned integer.
70pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> {
71    let mut buf = [0u8; size_of::<i128>()];
72    match MachineInfo::target_endianness() {
73        Endian::Little => {
74            bytes.read_exact(&mut buf[..bytes.len()])?;
75            Ok(i128::from_le_bytes(buf))
76        }
77        Endian::Big => {
78            bytes.read_exact(&mut buf[16 - bytes.len()..])?;
79            Ok(i128::from_be_bytes(buf))
80        }
81    }
82}