| //! This module provides methods to retrieve allocation information, such as static variables. |
| |
| use std::io::Read; |
| |
| use serde::Serialize; |
| |
| use crate::mir::mono::{Instance, StaticDef}; |
| use crate::target::{Endian, MachineInfo}; |
| use crate::ty::{Allocation, Binder, ExistentialTraitRef, Ty}; |
| use crate::{Error, IndexedVal, with}; |
| |
| /// An allocation in the rustc_public's IR global memory can be either a function pointer, |
| /// a static, or a "real" allocation with some data in it. |
| #[derive(Debug, Clone, Eq, PartialEq, Serialize)] |
| pub enum GlobalAlloc { |
| /// The alloc ID is used as a function pointer. |
| Function(Instance), |
| /// This alloc ID points to a symbolic (not-reified) vtable. |
| /// The `None` trait ref is used to represent auto traits. |
| VTable(Ty, Option<Binder<ExistentialTraitRef>>), |
| /// The alloc ID points to a "lazy" static variable that did not get computed (yet). |
| /// This is also used to break the cycle in recursive statics. |
| Static(StaticDef), |
| /// The alloc ID points to memory. |
| Memory(Allocation), |
| /// The first pointer-sized segment of a type id. On 64 bit systems, the 128 bit type id |
| /// is split into two segments, on 32 bit systems there are 4 segments, and so on. |
| TypeId { ty: Ty }, |
| } |
| |
| impl From<AllocId> for GlobalAlloc { |
| fn from(value: AllocId) -> Self { |
| with(|cx| cx.global_alloc(value)) |
| } |
| } |
| |
| impl GlobalAlloc { |
| /// Retrieve the allocation id for a global allocation if it exists. |
| /// |
| /// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given |
| /// type for the optional trait if the type implements the trait. |
| /// |
| /// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`. |
| pub fn vtable_allocation(&self) -> Option<AllocId> { |
| with(|cx| cx.vtable_allocation(self)) |
| } |
| } |
| |
| /// A unique identification number for each provenance |
| #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] |
| pub struct AllocId(usize); |
| |
| impl IndexedVal for AllocId { |
| fn to_val(index: usize) -> Self { |
| AllocId(index) |
| } |
| fn to_index(&self) -> usize { |
| self.0 |
| } |
| } |
| |
| /// Utility function used to read an allocation data into a unassigned integer. |
| pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> { |
| let mut buf = [0u8; size_of::<u128>()]; |
| match MachineInfo::target_endianness() { |
| Endian::Little => { |
| bytes.read_exact(&mut buf[..bytes.len()])?; |
| Ok(u128::from_le_bytes(buf)) |
| } |
| Endian::Big => { |
| bytes.read_exact(&mut buf[16 - bytes.len()..])?; |
| Ok(u128::from_be_bytes(buf)) |
| } |
| } |
| } |
| |
| /// Utility function used to read an allocation data into an assigned integer. |
| pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> { |
| let mut buf = [0u8; size_of::<i128>()]; |
| match MachineInfo::target_endianness() { |
| Endian::Little => { |
| bytes.read_exact(&mut buf[..bytes.len()])?; |
| Ok(i128::from_le_bytes(buf)) |
| } |
| Endian::Big => { |
| bytes.read_exact(&mut buf[16 - bytes.len()..])?; |
| Ok(i128::from_be_bytes(buf)) |
| } |
| } |
| } |