miri/
alloc_bytes.rs
1use std::alloc::Layout;
2use std::borrow::Cow;
3use std::{alloc, slice};
4
5use rustc_abi::{Align, Size};
6use rustc_middle::mir::interpret::AllocBytes;
7
8#[derive(Debug)]
11pub struct MiriAllocBytes {
12 layout: alloc::Layout,
14 ptr: *mut u8,
19}
20
21impl Clone for MiriAllocBytes {
22 fn clone(&self) -> Self {
23 let bytes: Cow<'_, [u8]> = Cow::Borrowed(self);
24 let align = Align::from_bytes(self.layout.align().try_into().unwrap()).unwrap();
25 MiriAllocBytes::from_bytes(bytes, align)
26 }
27}
28
29impl Drop for MiriAllocBytes {
30 fn drop(&mut self) {
31 let alloc_layout = if self.layout.size() == 0 {
34 Layout::from_size_align(1, self.layout.align()).unwrap()
35 } else {
36 self.layout
37 };
38 unsafe { alloc::dealloc(self.ptr, alloc_layout) }
40 }
41}
42
43impl std::ops::Deref for MiriAllocBytes {
44 type Target = [u8];
45
46 fn deref(&self) -> &Self::Target {
47 unsafe { slice::from_raw_parts(self.ptr, self.layout.size()) }
50 }
51}
52
53impl std::ops::DerefMut for MiriAllocBytes {
54 fn deref_mut(&mut self) -> &mut Self::Target {
55 unsafe { slice::from_raw_parts_mut(self.ptr, self.layout.size()) }
58 }
59}
60
61impl MiriAllocBytes {
62 fn alloc_with(
66 size: u64,
67 align: u64,
68 alloc_fn: impl FnOnce(Layout) -> *mut u8,
69 ) -> Result<MiriAllocBytes, ()> {
70 let size = usize::try_from(size).map_err(|_| ())?;
71 let align = usize::try_from(align).map_err(|_| ())?;
72 let layout = Layout::from_size_align(size, align).map_err(|_| ())?;
73 let alloc_layout =
75 if size == 0 { Layout::from_size_align(1, align).unwrap() } else { layout };
76 let ptr = alloc_fn(alloc_layout);
77 if ptr.is_null() {
78 Err(())
79 } else {
80 Ok(Self { ptr, layout })
82 }
83 }
84}
85
86impl AllocBytes for MiriAllocBytes {
87 fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
88 let slice = slice.into();
89 let size = slice.len();
90 let align = align.bytes();
91 let alloc_fn = |layout| unsafe { alloc::alloc(layout) };
93 let alloc_bytes = MiriAllocBytes::alloc_with(size.try_into().unwrap(), align, alloc_fn)
94 .unwrap_or_else(|()| {
95 panic!("Miri ran out of memory: cannot create allocation of {size} bytes")
96 });
97 unsafe { alloc_bytes.ptr.copy_from(slice.as_ptr(), size) };
100 alloc_bytes
101 }
102
103 fn zeroed(size: Size, align: Align) -> Option<Self> {
104 let size = size.bytes();
105 let align = align.bytes();
106 let alloc_fn = |layout| unsafe { alloc::alloc_zeroed(layout) };
108 MiriAllocBytes::alloc_with(size, align, alloc_fn).ok()
109 }
110
111 fn as_mut_ptr(&mut self) -> *mut u8 {
112 self.ptr
113 }
114
115 fn as_ptr(&self) -> *const u8 {
116 self.ptr
117 }
118}