stable_mir/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, IndexedVal, Ty};
10use crate::{Error, with};
11
12/// An allocation in the SMIR global memory can be either a function pointer,
13/// a static, or a "real" allocation with some data in it.
14#[derive(Debug, Clone, Eq, PartialEq, 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}
27
28impl From<AllocId> for GlobalAlloc {
29    fn from(value: AllocId) -> Self {
30        with(|cx| cx.global_alloc(value))
31    }
32}
33
34impl GlobalAlloc {
35    /// Retrieve the allocation id for a global allocation if it exists.
36    ///
37    /// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given
38    /// type for the optional trait if the type implements the trait.
39    ///
40    /// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`.
41    pub fn vtable_allocation(&self) -> Option<AllocId> {
42        with(|cx| cx.vtable_allocation(self))
43    }
44}
45
46/// A unique identification number for each provenance
47#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
48pub struct AllocId(usize);
49
50impl IndexedVal for AllocId {
51    fn to_val(index: usize) -> Self {
52        AllocId(index)
53    }
54    fn to_index(&self) -> usize {
55        self.0
56    }
57}
58
59/// Utility function used to read an allocation data into a unassigned integer.
60pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
61    let mut buf = [0u8; std::mem::size_of::<u128>()];
62    match MachineInfo::target_endianness() {
63        Endian::Little => {
64            bytes.read_exact(&mut buf[..bytes.len()])?;
65            Ok(u128::from_le_bytes(buf))
66        }
67        Endian::Big => {
68            bytes.read_exact(&mut buf[16 - bytes.len()..])?;
69            Ok(u128::from_be_bytes(buf))
70        }
71    }
72}
73
74/// Utility function used to read an allocation data into an assigned integer.
75pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> {
76    let mut buf = [0u8; std::mem::size_of::<i128>()];
77    match MachineInfo::target_endianness() {
78        Endian::Little => {
79            bytes.read_exact(&mut buf[..bytes.len()])?;
80            Ok(i128::from_le_bytes(buf))
81        }
82        Endian::Big => {
83            bytes.read_exact(&mut buf[16 - bytes.len()..])?;
84            Ok(i128::from_be_bytes(buf))
85        }
86    }
87}