//! Memory allocation implementation for rustc_public. //! //! This module is responsible for constructing stable components. //! All operations requiring rustc queries must be delegated //! to `rustc_public_bridge::alloc` to maintain stability guarantees. use rustc_abi::Align; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::AllocRange; use rustc_public_bridge::bridge::Error as _; use rustc_public_bridge::context::CompilerCtxt; use rustc_public_bridge::{Tables, alloc}; use super::Error; use super::compiler_interface::BridgeTys; use super::mir::Mutability; use super::ty::{Allocation, ProvenanceMap}; use super::unstable::Stable; /// Creates new empty `Allocation` from given `Align`. fn new_empty_allocation(align: Align) -> Allocation { Allocation { bytes: Vec::new(), provenance: ProvenanceMap { ptrs: Vec::new() }, align: align.bytes(), mutability: Mutability::Not, } } // We need this method instead of a Stable implementation // because we need to get `Ty` of the const we are trying to create, to do that // we need to have access to `ConstantKind` but we can't access that inside Stable impl. #[allow(rustc::usage_of_qualified_ty)] pub(crate) fn new_allocation<'tcx>( ty: rustc_middle::ty::Ty<'tcx>, const_value: ConstValue, tables: &mut Tables<'tcx, BridgeTys>, cx: &CompilerCtxt<'tcx, BridgeTys>, ) -> Allocation { try_new_allocation(ty, const_value, tables, cx) .unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}")) } #[allow(rustc::usage_of_qualified_ty)] pub(crate) fn try_new_allocation<'tcx>( ty: rustc_middle::ty::Ty<'tcx>, const_value: ConstValue, tables: &mut Tables<'tcx, BridgeTys>, cx: &CompilerCtxt<'tcx, BridgeTys>, ) -> Result { let layout = alloc::create_ty_and_layout(cx, ty).map_err(|e| Error::from_internal(e))?; match const_value { ConstValue::Scalar(scalar) => { alloc::try_new_scalar(layout, scalar, cx).map(|alloc| alloc.stable(tables, cx)) } ConstValue::ZeroSized => Ok(new_empty_allocation(layout.align.abi)), ConstValue::Slice { alloc_id, meta } => { alloc::try_new_slice(layout, alloc_id, meta, cx).map(|alloc| alloc.stable(tables, cx)) } ConstValue::Indirect { alloc_id, offset } => { let alloc = alloc::try_new_indirect(alloc_id, cx); use rustc_public_bridge::context::AllocRangeHelpers; Ok(allocation_filter(&alloc.0, cx.alloc_range(offset, layout.size), tables, cx)) } } } /// Creates an `Allocation` only from information within the `AllocRange`. pub(super) fn allocation_filter<'tcx>( alloc: &rustc_middle::mir::interpret::Allocation, alloc_range: AllocRange, tables: &mut Tables<'tcx, BridgeTys>, cx: &CompilerCtxt<'tcx, BridgeTys>, ) -> Allocation { alloc::allocation_filter(alloc, alloc_range, tables, cx) }