rustc_smir/rustc_smir/
alloc.rs1use rustc_abi::{Align, Size};
2use rustc_middle::mir::ConstValue;
3use rustc_middle::mir::interpret::{AllocInit, AllocRange, Pointer, alloc_range};
4use stable_mir::Error;
5use stable_mir::mir::Mutability;
6use stable_mir::ty::{Allocation, ProvenanceMap};
7
8use crate::rustc_smir::{Stable, Tables};
9
10fn new_empty_allocation(align: Align) -> Allocation {
12 Allocation {
13 bytes: Vec::new(),
14 provenance: ProvenanceMap { ptrs: Vec::new() },
15 align: align.bytes(),
16 mutability: Mutability::Not,
17 }
18}
19
20#[allow(rustc::usage_of_qualified_ty)]
24pub(crate) fn new_allocation<'tcx>(
25 ty: rustc_middle::ty::Ty<'tcx>,
26 const_value: ConstValue<'tcx>,
27 tables: &mut Tables<'tcx>,
28) -> Allocation {
29 try_new_allocation(ty, const_value, tables)
30 .expect(&format!("Failed to convert: {const_value:?} to {ty:?}"))
31}
32
33#[allow(rustc::usage_of_qualified_ty)]
34pub(crate) fn try_new_allocation<'tcx>(
35 ty: rustc_middle::ty::Ty<'tcx>,
36 const_value: ConstValue<'tcx>,
37 tables: &mut Tables<'tcx>,
38) -> Result<Allocation, Error> {
39 Ok(match const_value {
40 ConstValue::Scalar(scalar) => {
41 let size = scalar.size();
42 let align = tables
43 .tcx
44 .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
45 .map_err(|e| e.stable(tables))?
46 .align;
47 let mut allocation =
48 rustc_middle::mir::interpret::Allocation::new(size, align.abi, AllocInit::Uninit);
49 allocation
50 .write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
51 .map_err(|e| e.stable(tables))?;
52 allocation.stable(tables)
53 }
54 ConstValue::ZeroSized => {
55 let align = tables
56 .tcx
57 .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
58 .map_err(|e| e.stable(tables))?
59 .align;
60 new_empty_allocation(align.abi)
61 }
62 ConstValue::Slice { data, meta } => {
63 let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data);
64 let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
65 let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
66 let scalar_meta =
67 rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx);
68 let layout = tables
69 .tcx
70 .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
71 .map_err(|e| e.stable(tables))?;
72 let mut allocation = rustc_middle::mir::interpret::Allocation::new(
73 layout.size,
74 layout.align.abi,
75 AllocInit::Uninit,
76 );
77 allocation
78 .write_scalar(
79 &tables.tcx,
80 alloc_range(Size::ZERO, tables.tcx.data_layout.pointer_size),
81 scalar_ptr,
82 )
83 .map_err(|e| e.stable(tables))?;
84 allocation
85 .write_scalar(
86 &tables.tcx,
87 alloc_range(tables.tcx.data_layout.pointer_size, scalar_meta.size()),
88 scalar_meta,
89 )
90 .map_err(|e| e.stable(tables))?;
91 allocation.stable(tables)
92 }
93 ConstValue::Indirect { alloc_id, offset } => {
94 let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
95 let ty_size = tables
96 .tcx
97 .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
98 .map_err(|e| e.stable(tables))?
99 .size;
100 allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
101 }
102 })
103}
104
105pub(super) fn allocation_filter<'tcx>(
107 alloc: &rustc_middle::mir::interpret::Allocation,
108 alloc_range: AllocRange,
109 tables: &mut Tables<'tcx>,
110) -> Allocation {
111 let mut bytes: Vec<Option<u8>> = alloc
112 .inspect_with_uninit_and_ptr_outside_interpreter(
113 alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
114 )
115 .iter()
116 .copied()
117 .map(Some)
118 .collect();
119 for (i, b) in bytes.iter_mut().enumerate() {
120 if !alloc.init_mask().get(Size::from_bytes(i + alloc_range.start.bytes_usize())) {
121 *b = None;
122 }
123 }
124 let mut ptrs = Vec::new();
125 for (offset, prov) in alloc
126 .provenance()
127 .ptrs()
128 .iter()
129 .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
130 {
131 ptrs.push((
132 offset.bytes_usize() - alloc_range.start.bytes_usize(),
133 tables.prov(prov.alloc_id()),
134 ));
135 }
136 Allocation {
137 bytes,
138 provenance: ProvenanceMap { ptrs },
139 align: alloc.align.bytes(),
140 mutability: alloc.mutability.stable(tables),
141 }
142}