1use rustc_abi::{Size, TyAndLayout};
8use rustc_middle::mir::interpret::{
9 AllocId, AllocInit, AllocRange, Allocation, ConstAllocation, Pointer, Scalar, alloc_range,
10};
11use rustc_middle::ty::{Ty, layout};
12
13use super::{SmirCtxt, Tables};
14use crate::bridge::Allocation as _;
15use crate::{Bridge, SmirError};
16
17pub fn create_ty_and_layout<'tcx, B: Bridge>(
18 cx: &SmirCtxt<'tcx, B>,
19 ty: Ty<'tcx>,
20) -> Result<TyAndLayout<'tcx, Ty<'tcx>>, &'tcx layout::LayoutError<'tcx>> {
21 use crate::context::SmirTypingEnv;
22 cx.tcx.layout_of(cx.fully_monomorphized().as_query_input(ty))
23}
24
25pub fn try_new_scalar<'tcx, B: Bridge>(
26 layout: TyAndLayout<'tcx, Ty<'tcx>>,
27 scalar: Scalar,
28 cx: &SmirCtxt<'tcx, B>,
29) -> Result<Allocation, B::Error> {
30 let size = scalar.size();
31 let mut allocation = Allocation::new(size, layout.align.abi, AllocInit::Uninit, ());
32 allocation
33 .write_scalar(&cx.tcx, alloc_range(Size::ZERO, size), scalar)
34 .map_err(|e| B::Error::from_internal(e))?;
35
36 Ok(allocation)
37}
38
39pub fn try_new_slice<'tcx, B: Bridge>(
40 layout: TyAndLayout<'tcx, Ty<'tcx>>,
41 data: ConstAllocation<'tcx>,
42 meta: u64,
43 cx: &SmirCtxt<'tcx, B>,
44) -> Result<Allocation, B::Error> {
45 let alloc_id = cx.tcx.reserve_and_set_memory_alloc(data);
46 let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
47 let scalar_ptr = Scalar::from_pointer(ptr, &cx.tcx);
48 let scalar_meta: Scalar = Scalar::from_target_usize(meta, &cx.tcx);
49 let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ());
50 let ptr_size = cx.tcx.data_layout.pointer_size();
51 allocation
52 .write_scalar(&cx.tcx, alloc_range(Size::ZERO, ptr_size), scalar_ptr)
53 .map_err(|e| B::Error::from_internal(e))?;
54 allocation
55 .write_scalar(&cx.tcx, alloc_range(ptr_size, scalar_meta.size()), scalar_meta)
56 .map_err(|e| B::Error::from_internal(e))?;
57
58 Ok(allocation)
59}
60
61pub fn try_new_indirect<'tcx, B: Bridge>(
62 alloc_id: AllocId,
63 cx: &SmirCtxt<'tcx, B>,
64) -> ConstAllocation<'tcx> {
65 let alloc = cx.tcx.global_alloc(alloc_id).unwrap_memory();
66
67 alloc
68}
69
70pub fn allocation_filter<'tcx, B: Bridge>(
72 alloc: &rustc_middle::mir::interpret::Allocation,
73 alloc_range: AllocRange,
74 tables: &mut Tables<'tcx, B>,
75 cx: &SmirCtxt<'tcx, B>,
76) -> B::Allocation {
77 let mut bytes: Vec<Option<u8>> = alloc
78 .inspect_with_uninit_and_ptr_outside_interpreter(
79 alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
80 )
81 .iter()
82 .copied()
83 .map(Some)
84 .collect();
85 for (i, b) in bytes.iter_mut().enumerate() {
86 if !alloc.init_mask().get(Size::from_bytes(i + alloc_range.start.bytes_usize())) {
87 *b = None;
88 }
89 }
90 let mut ptrs = Vec::new();
91 for (offset, prov) in alloc
92 .provenance()
93 .ptrs()
94 .iter()
95 .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
96 {
97 ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), prov.alloc_id()));
98 }
99
100 B::Allocation::new(bytes, ptrs, alloc.align.bytes(), alloc.mutability, tables, cx)
101}