stable_mir/
alloc.rs

1//! Memory allocation implementation for StableMIR.
2//!
3//! This module is responsible for constructing stable components.
4//! All operations requiring rustc queries must be delegated
5//! to `rustc_smir::alloc` to maintain stability guarantees.
6
7use rustc_abi::Align;
8use rustc_middle::mir::ConstValue;
9use rustc_middle::mir::interpret::AllocRange;
10use rustc_smir::bridge::SmirError;
11use rustc_smir::context::SmirCtxt;
12use rustc_smir::{Tables, alloc};
13
14use super::Error;
15use super::compiler_interface::BridgeTys;
16use super::mir::Mutability;
17use super::ty::{Allocation, ProvenanceMap};
18use super::unstable::Stable;
19
20/// Creates new empty `Allocation` from given `Align`.
21fn new_empty_allocation(align: Align) -> Allocation {
22    Allocation {
23        bytes: Vec::new(),
24        provenance: ProvenanceMap { ptrs: Vec::new() },
25        align: align.bytes(),
26        mutability: Mutability::Not,
27    }
28}
29
30// We need this method instead of a Stable implementation
31// because we need to get `Ty` of the const we are trying to create, to do that
32// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
33#[allow(rustc::usage_of_qualified_ty)]
34pub(crate) fn new_allocation<'tcx>(
35    ty: rustc_middle::ty::Ty<'tcx>,
36    const_value: ConstValue<'tcx>,
37    tables: &mut Tables<'tcx, BridgeTys>,
38    cx: &SmirCtxt<'tcx, BridgeTys>,
39) -> Allocation {
40    try_new_allocation(ty, const_value, tables, cx)
41        .unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}"))
42}
43
44#[allow(rustc::usage_of_qualified_ty)]
45pub(crate) fn try_new_allocation<'tcx>(
46    ty: rustc_middle::ty::Ty<'tcx>,
47    const_value: ConstValue<'tcx>,
48    tables: &mut Tables<'tcx, BridgeTys>,
49    cx: &SmirCtxt<'tcx, BridgeTys>,
50) -> Result<Allocation, Error> {
51    let layout = alloc::create_ty_and_layout(cx, ty).map_err(|e| Error::from_internal(e))?;
52    match const_value {
53        ConstValue::Scalar(scalar) => {
54            alloc::try_new_scalar(layout, scalar, cx).map(|alloc| alloc.stable(tables, cx))
55        }
56        ConstValue::ZeroSized => Ok(new_empty_allocation(layout.align.abi)),
57        ConstValue::Slice { data, meta } => {
58            alloc::try_new_slice(layout, data, meta, cx).map(|alloc| alloc.stable(tables, cx))
59        }
60        ConstValue::Indirect { alloc_id, offset } => {
61            let alloc = alloc::try_new_indirect(alloc_id, cx);
62            use rustc_smir::context::SmirAllocRange;
63            Ok(allocation_filter(&alloc.0, cx.alloc_range(offset, layout.size), tables, cx))
64        }
65    }
66}
67
68/// Creates an `Allocation` only from information within the `AllocRange`.
69pub(super) fn allocation_filter<'tcx>(
70    alloc: &rustc_middle::mir::interpret::Allocation,
71    alloc_range: AllocRange,
72    tables: &mut Tables<'tcx, BridgeTys>,
73    cx: &SmirCtxt<'tcx, BridgeTys>,
74) -> Allocation {
75    alloc::allocation_filter(alloc, alloc_range, tables, cx)
76}