Skip to content

Commit f37fe37

Browse files
committed
DO NOT MERGE - scratchwork
Punch a hole to allow direct access to bytes - this API should be changed to provide a `Size` value corresponding to an `AllocId`. Additionally, force bytes to be appropriately aligned - the current trick is a hack, and over-aligns. We should use the `Align` parameter to appropriately align these buffers, as otherwise they'll never be able to be used by native code. The "adjust" callback used on deserialized allocations might not have that information - if it doesn't, just overalign to max alignment
1 parent 0fe75b8 commit f37fe37

File tree

5 files changed

+69
-9
lines changed

5 files changed

+69
-9
lines changed

Cargo.lock

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
# It is not intended for manual editing.
33
version = 3
44

5+
[[package]]
6+
name = "abort_on_panic"
7+
version = "2.0.0"
8+
source = "registry+https://github.com/rust-lang/crates.io-index"
9+
checksum = "955f37ac58af2416bac687c8ab66a4ccba282229bd7422a28d2281a5e66a6116"
10+
511
[[package]]
612
name = "addr2line"
713
version = "0.16.0"
@@ -2151,6 +2157,26 @@ dependencies = [
21512157
"rustc-std-workspace-core",
21522158
]
21532159

2160+
[[package]]
2161+
name = "libffi"
2162+
version = "3.0.0"
2163+
source = "registry+https://github.com/rust-lang/crates.io-index"
2164+
checksum = "0e08093a2ddeee94bd0c830a53d895ff91f1f3bb0f9b3c8c6b00739cdf76bc1d"
2165+
dependencies = [
2166+
"abort_on_panic",
2167+
"libc",
2168+
"libffi-sys",
2169+
]
2170+
2171+
[[package]]
2172+
name = "libffi-sys"
2173+
version = "2.0.0"
2174+
source = "registry+https://github.com/rust-lang/crates.io-index"
2175+
checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
2176+
dependencies = [
2177+
"cc",
2178+
]
2179+
21542180
[[package]]
21552181
name = "libgit2-sys"
21562182
version = "0.13.2+1.4.2"
@@ -2482,6 +2508,8 @@ dependencies = [
24822508
"getrandom 0.2.0",
24832509
"lazy_static",
24842510
"libc",
2511+
"libffi",
2512+
"libloading",
24852513
"log",
24862514
"measureme",
24872515
"rand 0.8.5",

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
520520

521521
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
522522
/// The caller is responsible for calling the access hooks!
523-
fn get_alloc_raw(
523+
pub fn get_alloc_raw(
524524
&self,
525525
id: AllocId,
526526
) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra>> {

compiler/rustc_middle/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#![feature(intra_doc_pointers)]
6161
#![feature(yeet_expr)]
6262
#![feature(const_option)]
63+
#![feature(vec_into_raw_parts)]
6364
#![recursion_limit = "512"]
6465
#![allow(rustc::potential_query_instability)]
6566

compiler/rustc_middle/src/mir/interpret/allocation.rs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::ty;
3333
pub struct Allocation<Prov = AllocId, Extra = ()> {
3434
/// The actual bytes of the allocation.
3535
/// Note that the bytes of a pointer represent the offset of the pointer.
36-
bytes: Box<[u8]>,
36+
pub bytes: Box<[u8]>,
3737
/// Maps from byte addresses to extra data for each pointer.
3838
/// Only the first byte of a pointer is inserted into the map; i.e.,
3939
/// every entry in this map applies to `pointer_size` consecutive bytes starting
@@ -207,8 +207,23 @@ impl<Prov> Allocation<Prov> {
207207
align: Align,
208208
mutability: Mutability,
209209
) -> Self {
210-
let bytes = Box::<[u8]>::from(slice.into());
211-
let size = Size::from_bytes(bytes.len());
210+
let slice: Cow<'a, [u8]> = slice.into();
211+
let size = Size::from_bytes(slice.len());
212+
// TODO come up with a cleaner way to align the box based on the alignment parameter
213+
let count128 = (slice.len() / 16) + 1;
214+
let mut vec128: Vec<u128> = Vec::with_capacity(count128);
215+
// TODO avoid excess initialization
216+
vec128.resize(count128, 0);
217+
let (buf, _len, _capacity) = vec128.into_raw_parts();
218+
assert!((buf as u64) % 16 == 0);
219+
let vec8: Vec<u8> = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())};
220+
assert!(vec8.as_ptr() as u64 % 16 == 0);
221+
//let mut vec8: Vec<u8> = unsafe {Vec::from_raw_parts(buf as *mut u8, len * 16, capacity * 16)};
222+
//vec8.truncate(size.bytes_usize());
223+
let mut bytes = vec8.into_boxed_slice();
224+
assert!(bytes.as_ptr() as u64 % 16 == 0);
225+
bytes.copy_from_slice(&slice);
226+
212227
Self {
213228
bytes,
214229
relocations: Relocations::new(),
@@ -228,7 +243,17 @@ impl<Prov> Allocation<Prov> {
228243
///
229244
/// If `panic_on_fail` is true, this will never return `Err`.
230245
pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
231-
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
246+
let count128 = (size.bytes_usize() / 16) + 1;
247+
// TODO this one is supposed to handle allocation failure, so do so.
248+
let mut vec128: Vec<u128> = Vec::with_capacity(count128);
249+
vec128.resize(count128, 0);
250+
let (buf, _len, _capacity) = vec128.into_raw_parts();
251+
assert!((buf as u64) % 16 == 0);
252+
let vec8: Vec<u8> = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())};
253+
assert!(vec8.as_ptr() as u64 % 16 == 0);
254+
let bytes = vec8.into_boxed_slice();
255+
assert!(bytes.as_ptr() as u64 % 16 == 0);
256+
Ok(()).map_err(|_: ()| {
232257
// This results in an error that can happen non-deterministically, since the memory
233258
// available to the compiler can change between runs. Normally queries are always
234259
// deterministic. However, we can be non-deterministic here because all uses of const
@@ -242,8 +267,6 @@ impl<Prov> Allocation<Prov> {
242267
});
243268
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
244269
})?;
245-
// SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
246-
let bytes = unsafe { bytes.assume_init() };
247270
Ok(Allocation {
248271
bytes,
249272
relocations: Relocations::new(),
@@ -265,7 +288,14 @@ impl Allocation {
265288
mut adjust_ptr: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Prov>, Err>,
266289
) -> Result<Allocation<Prov, Extra>, Err> {
267290
// Compute new pointer provenance, which also adjusts the bytes.
268-
let mut bytes = self.bytes;
291+
// Realign the pointer
292+
let count128 = (self.bytes.len() / 16) + 1;
293+
let mut vec128: Vec<u128> = Vec::with_capacity(count128);
294+
vec128.resize(count128, 0);
295+
let (buf, _len, _capacity) = vec128.into_raw_parts();
296+
let mut vec8: Vec<u8> = unsafe {Vec::from_raw_parts(buf as *mut u8, self.bytes.len(), self.bytes.len())};
297+
vec8[..self.bytes.len()].copy_from_slice(&self.bytes);
298+
let mut bytes = vec8.into_boxed_slice();
269299
let mut new_relocations = Vec::with_capacity(self.relocations.0.len());
270300
let ptr_size = cx.data_layout().pointer_size.bytes_usize();
271301
let endian = cx.data_layout().endian;
@@ -278,6 +308,7 @@ impl Allocation {
278308
write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap();
279309
new_relocations.push((offset, ptr_prov));
280310
}
311+
assert!(bytes.as_ptr() as u64 % 16 == 0);
281312
// Create allocation.
282313
Ok(Allocation {
283314
bytes,

0 commit comments

Comments
 (0)