rustc_smir/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;
6use stable_mir::mir::mono::{Instance, StaticDef};
7use stable_mir::target::{Endian, MachineInfo};
8use stable_mir::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
9use stable_mir::{Error, with};
10
11use crate::stable_mir;
12
13/// An allocation in the SMIR global memory can be either a function pointer,
14/// a static, or a "real" allocation with some data in it.
15#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
16pub enum GlobalAlloc {
17    /// The alloc ID is used as a function pointer.
18    Function(Instance),
19    /// This alloc ID points to a symbolic (not-reified) vtable.
20    /// The `None` trait ref is used to represent auto traits.
21    VTable(Ty, Option<Binder<ExistentialTraitRef>>),
22    /// The alloc ID points to a "lazy" static variable that did not get computed (yet).
23    /// This is also used to break the cycle in recursive statics.
24    Static(StaticDef),
25    /// The alloc ID points to memory.
26    Memory(Allocation),
27}
28
29impl From<AllocId> for GlobalAlloc {
30    fn from(value: AllocId) -> Self {
31        with(|cx| cx.global_alloc(value))
32    }
33}
34
35impl GlobalAlloc {
36    /// Retrieve the allocation id for a global allocation if it exists.
37    ///
38    /// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given
39    /// type for the optional trait if the type implements the trait.
40    ///
41    /// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`.
42    pub fn vtable_allocation(&self) -> Option<AllocId> {
43        with(|cx| cx.vtable_allocation(self))
44    }
45}
46
47/// A unique identification number for each provenance
48#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
49pub struct AllocId(usize);
50
51impl IndexedVal for AllocId {
52    fn to_val(index: usize) -> Self {
53        AllocId(index)
54    }
55    fn to_index(&self) -> usize {
56        self.0
57    }
58}
59
60/// Utility function used to read an allocation data into a unassigned integer.
61pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
62    let mut buf = [0u8; size_of::<u128>()];
63    match MachineInfo::target_endianness() {
64        Endian::Little => {
65            bytes.read_exact(&mut buf[..bytes.len()])?;
66            Ok(u128::from_le_bytes(buf))
67        }
68        Endian::Big => {
69            bytes.read_exact(&mut buf[16 - bytes.len()..])?;
70            Ok(u128::from_be_bytes(buf))
71        }
72    }
73}
74
75/// Utility function used to read an allocation data into an assigned integer.
76pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> {
77    let mut buf = [0u8; size_of::<i128>()];
78    match MachineInfo::target_endianness() {
79        Endian::Little => {
80            bytes.read_exact(&mut buf[..bytes.len()])?;
81            Ok(i128::from_le_bytes(buf))
82        }
83        Endian::Big => {
84            bytes.read_exact(&mut buf[16 - bytes.len()..])?;
85            Ok(i128::from_be_bytes(buf))
86        }
87    }
88}