From 0fe75b8a3f4a6fdce3b202052964f3b86cb07f7b Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 2 Aug 2022 15:01:11 -0700 Subject: [PATCH 01/24] Stop x.py from being mean --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index b938529fb8ed8..47c954693bcca 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit b938529fb8ed8f7b5b374282ffc3ffa74c313111 +Subproject commit 47c954693bcca64838f1757b3de27640623cc8b1 From f37fe3771de5db4211f54095546f85dc3acc2ba7 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 2 Aug 2022 22:22:48 -0700 Subject: [PATCH 02/24] 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 --- Cargo.lock | 28 ++++++++++++ .../rustc_const_eval/src/interpret/memory.rs | 2 +- compiler/rustc_middle/src/lib.rs | 1 + .../src/mir/interpret/allocation.rs | 45 ++++++++++++++++--- src/tools/miri | 2 +- 5 files changed, 69 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 058b6198dc425..7e13570834e8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "abort_on_panic" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955f37ac58af2416bac687c8ab66a4ccba282229bd7422a28d2281a5e66a6116" + [[package]] name = "addr2line" version = "0.16.0" @@ -2151,6 +2157,26 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "libffi" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e08093a2ddeee94bd0c830a53d895ff91f1f3bb0f9b3c8c6b00739cdf76bc1d" +dependencies = [ + "abort_on_panic", + "libc", + "libffi-sys", +] + +[[package]] +name = "libffi-sys" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15" +dependencies = [ + "cc", +] + [[package]] name = "libgit2-sys" version = "0.13.2+1.4.2" @@ -2482,6 +2508,8 @@ dependencies = [ "getrandom 0.2.0", "lazy_static", "libc", + "libffi", + "libloading", "log", "measureme", "rand 0.8.5", diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index ed2c4edf9dd72..4b1f9f3e768f4 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -520,7 +520,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Gives raw access to the `Allocation`, without bounds or alignment checks. /// The caller is responsible for calling the access hooks! - fn get_alloc_raw( + pub fn get_alloc_raw( &self, id: AllocId, ) -> InterpResult<'tcx, &Allocation> { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 45c6468bc24e5..a07285bc3e540 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -60,6 +60,7 @@ #![feature(intra_doc_pointers)] #![feature(yeet_expr)] #![feature(const_option)] +#![feature(vec_into_raw_parts)] #![recursion_limit = "512"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index db7e0fb8a3bdb..298cd689be0f5 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -33,7 +33,7 @@ use crate::ty; pub struct Allocation { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. - bytes: Box<[u8]>, + pub bytes: Box<[u8]>, /// Maps from byte addresses to extra data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting @@ -207,8 +207,23 @@ impl Allocation { align: Align, mutability: Mutability, ) -> Self { - let bytes = Box::<[u8]>::from(slice.into()); - let size = Size::from_bytes(bytes.len()); + let slice: Cow<'a, [u8]> = slice.into(); + let size = Size::from_bytes(slice.len()); + // TODO come up with a cleaner way to align the box based on the alignment parameter + let count128 = (slice.len() / 16) + 1; + let mut vec128: Vec = Vec::with_capacity(count128); + // TODO avoid excess initialization + vec128.resize(count128, 0); + let (buf, _len, _capacity) = vec128.into_raw_parts(); + assert!((buf as u64) % 16 == 0); + let vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; + assert!(vec8.as_ptr() as u64 % 16 == 0); + //let mut vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, len * 16, capacity * 16)}; + //vec8.truncate(size.bytes_usize()); + let mut bytes = vec8.into_boxed_slice(); + assert!(bytes.as_ptr() as u64 % 16 == 0); + bytes.copy_from_slice(&slice); + Self { bytes, relocations: Relocations::new(), @@ -228,7 +243,17 @@ impl Allocation { /// /// If `panic_on_fail` is true, this will never return `Err`. pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> { - let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| { + let count128 = (size.bytes_usize() / 16) + 1; + // TODO this one is supposed to handle allocation failure, so do so. + let mut vec128: Vec = Vec::with_capacity(count128); + vec128.resize(count128, 0); + let (buf, _len, _capacity) = vec128.into_raw_parts(); + assert!((buf as u64) % 16 == 0); + let vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; + assert!(vec8.as_ptr() as u64 % 16 == 0); + let bytes = vec8.into_boxed_slice(); + assert!(bytes.as_ptr() as u64 % 16 == 0); + Ok(()).map_err(|_: ()| { // This results in an error that can happen non-deterministically, since the memory // available to the compiler can change between runs. Normally queries are always // deterministic. However, we can be non-deterministic here because all uses of const @@ -242,8 +267,6 @@ impl Allocation { }); InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) })?; - // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> - let bytes = unsafe { bytes.assume_init() }; Ok(Allocation { bytes, relocations: Relocations::new(), @@ -265,7 +288,14 @@ impl Allocation { mut adjust_ptr: impl FnMut(Pointer) -> Result, Err>, ) -> Result, Err> { // Compute new pointer provenance, which also adjusts the bytes. - let mut bytes = self.bytes; + // Realign the pointer + let count128 = (self.bytes.len() / 16) + 1; + let mut vec128: Vec = Vec::with_capacity(count128); + vec128.resize(count128, 0); + let (buf, _len, _capacity) = vec128.into_raw_parts(); + let mut vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, self.bytes.len(), self.bytes.len())}; + vec8[..self.bytes.len()].copy_from_slice(&self.bytes); + let mut bytes = vec8.into_boxed_slice(); let mut new_relocations = Vec::with_capacity(self.relocations.0.len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; @@ -278,6 +308,7 @@ impl Allocation { write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap(); new_relocations.push((offset, ptr_prov)); } + assert!(bytes.as_ptr() as u64 % 16 == 0); // Create allocation. Ok(Allocation { bytes, diff --git a/src/tools/miri b/src/tools/miri index 47c954693bcca..33ef5610317fa 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 47c954693bcca64838f1757b3de27640623cc8b1 +Subproject commit 33ef5610317fa1a214ea691bab0582c956c3f944 From fde4235ed5d9c26a4cd94da8cb20f51ffa5e0c4c Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Wed, 3 Aug 2022 22:58:31 +0000 Subject: [PATCH 03/24] point to my miri fork --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index cca60e337d2d8..8fa7a8673ef37 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,3 +41,6 @@ [submodule "library/backtrace"] path = library/backtrace url = https://github.com/rust-lang/backtrace-rs.git +[submodule "src/tools/miri/"] + url = https://github.com/emarteca/miri + branch = matt-alloc-hacks From e0e8e00a41824bd5b7c5d2a29adfd04743418e73 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Thu, 4 Aug 2022 23:18:57 +0000 Subject: [PATCH 04/24] no more direct hole punch to alloc bytes --- compiler/rustc_middle/src/mir/interpret/allocation.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 298cd689be0f5..13d1fcb1e2e7f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -33,7 +33,7 @@ use crate::ty; pub struct Allocation { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. - pub bytes: Box<[u8]>, + bytes: Box<[u8]>, /// Maps from byte addresses to extra data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting @@ -352,6 +352,11 @@ impl Allocation { /// Byte accessors. impl Allocation { + /// Get the pointer of the [u8] of bytes. + pub fn get_bytes_addr(&self) -> Size { + Size::from_bytes(self.bytes.as_ptr() as u64) + } + /// This is the entirely abstraction-violating way to just grab the raw bytes without /// caring about relocations. It just deduplicates some code between `read_scalar` /// and `get_bytes_internal`. From a7b7f195c03d51f14719870fdd4d7e8b1b3046af Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Thu, 4 Aug 2022 23:47:53 +0000 Subject: [PATCH 05/24] no more holepunch to bytes --- compiler/rustc_const_eval/src/interpret/memory.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 4b1f9f3e768f4..692c750fcd3dd 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -518,9 +518,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } + /// Get the base address for the bytes in an `Allocation` specified by the + /// `AllocID` passed in; error if no such allocation exists. + pub fn get_alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, Size> { + let alloc = self.get_alloc_raw(id)?; + Ok(alloc.get_bytes_addr()) + } + /// Gives raw access to the `Allocation`, without bounds or alignment checks. /// The caller is responsible for calling the access hooks! - pub fn get_alloc_raw( + fn get_alloc_raw( &self, id: AllocId, ) -> InterpResult<'tcx, &Allocation> { From f7a991b76ae1acfcd0cf1dd92e53717236fedf0b Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Sat, 6 Aug 2022 20:57:14 +0000 Subject: [PATCH 06/24] commented out alignment check for int-aligned addrs -- need to make the check make sense (should be len of bytes) for real addrs --- compiler/rustc_const_eval/src/interpret/memory.rs | 4 +++- compiler/rustc_middle/src/mir/interpret/allocation.rs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 692c750fcd3dd..648040aa67bc2 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -447,7 +447,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(align) = align { if M::force_int_for_alignment_check(self) { // `force_int_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true. - check_offset_align(ptr.addr().bytes(), align)?; + // TODO do a proper check here + // now, addr().bytes() will not give the size of the allocation, it'll be the address + // check_offset_align(ptr.addr().bytes(), align)?; } else { // Check allocation alignment and offset alignment. if alloc_align.bytes() < align.bytes() { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 13d1fcb1e2e7f..1327279b38ade 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -211,6 +211,7 @@ impl Allocation { let size = Size::from_bytes(slice.len()); // TODO come up with a cleaner way to align the box based on the alignment parameter let count128 = (slice.len() / 16) + 1; + // println!("ALIGN: {:?}, {:?}", (align.bytes())+1, count128); let mut vec128: Vec = Vec::with_capacity(count128); // TODO avoid excess initialization vec128.resize(count128, 0); @@ -289,6 +290,7 @@ impl Allocation { ) -> Result, Err> { // Compute new pointer provenance, which also adjusts the bytes. // Realign the pointer + // println!("adjusting: {:?}, {:?}", self.align, self.bytes.len()); let count128 = (self.bytes.len() / 16) + 1; let mut vec128: Vec = Vec::with_capacity(count128); vec128.resize(count128, 0); From e2ed272aecb2a9a389e1a062d722fbd2e9643799 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Sun, 7 Aug 2022 23:56:06 +0000 Subject: [PATCH 07/24] proper check for size of allocation being aligned --- compiler/rustc_const_eval/src/interpret/memory.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 648040aa67bc2..61e379f0132bb 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -449,7 +449,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // `force_int_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true. // TODO do a proper check here // now, addr().bytes() will not give the size of the allocation, it'll be the address - // check_offset_align(ptr.addr().bytes(), align)?; + // instead, get the allocation corresponding to this `AllocId` and get the size from it + let alloc = self.get_alloc_raw(alloc_id)?; + check_offset_align(alloc.size().bytes(), align)?; } else { // Check allocation alignment and offset alignment. if alloc_align.bytes() < align.bytes() { From 51269b88fbfa5975a6234e5973882686f51d778f Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Mon, 8 Aug 2022 21:37:48 +0000 Subject: [PATCH 08/24] using the align parameter to properly align allocations --- .../rustc_const_eval/src/interpret/memory.rs | 6 +- .../src/mir/interpret/allocation.rs | 63 +++++++++---------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 61e379f0132bb..692c750fcd3dd 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -447,11 +447,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(align) = align { if M::force_int_for_alignment_check(self) { // `force_int_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true. - // TODO do a proper check here - // now, addr().bytes() will not give the size of the allocation, it'll be the address - // instead, get the allocation corresponding to this `AllocId` and get the size from it - let alloc = self.get_alloc_raw(alloc_id)?; - check_offset_align(alloc.size().bytes(), align)?; + check_offset_align(ptr.addr().bytes(), align)?; } else { // Check allocation alignment and offset alignment. if alloc_align.bytes() < align.bytes() { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 1327279b38ade..43e7d52d8d4d4 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -209,21 +209,18 @@ impl Allocation { ) -> Self { let slice: Cow<'a, [u8]> = slice.into(); let size = Size::from_bytes(slice.len()); - // TODO come up with a cleaner way to align the box based on the alignment parameter - let count128 = (slice.len() / 16) + 1; - // println!("ALIGN: {:?}, {:?}", (align.bytes())+1, count128); - let mut vec128: Vec = Vec::with_capacity(count128); + let align_usize: usize = align.bytes().try_into().unwrap(); + let count_align = ((slice.len() / align_usize) + 1)*align_usize; + + let mut vec_align: Vec = Vec::with_capacity(count_align); + vec_align.resize(count_align, 0); // TODO avoid excess initialization - vec128.resize(count128, 0); - let (buf, _len, _capacity) = vec128.into_raw_parts(); - assert!((buf as u64) % 16 == 0); - let vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; - assert!(vec8.as_ptr() as u64 % 16 == 0); - //let mut vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, len * 16, capacity * 16)}; - //vec8.truncate(size.bytes_usize()); - let mut bytes = vec8.into_boxed_slice(); - assert!(bytes.as_ptr() as u64 % 16 == 0); - bytes.copy_from_slice(&slice); + let (buf, _len, _capacity) = vec_align.into_raw_parts(); + vec_align = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; + + let mut bytes = vec_align.into_boxed_slice(); + assert!(bytes.as_ptr() as u64 % align.bytes() == 0); + bytes[..slice.len()].copy_from_slice(&slice); Self { bytes, @@ -244,16 +241,16 @@ impl Allocation { /// /// If `panic_on_fail` is true, this will never return `Err`. pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> { - let count128 = (size.bytes_usize() / 16) + 1; + let align_usize: usize = align.bytes().try_into().unwrap(); + let count_align = ((size.bytes_usize() / align_usize) + 1)*align_usize; + // TODO this one is supposed to handle allocation failure, so do so. - let mut vec128: Vec = Vec::with_capacity(count128); - vec128.resize(count128, 0); - let (buf, _len, _capacity) = vec128.into_raw_parts(); - assert!((buf as u64) % 16 == 0); - let vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; - assert!(vec8.as_ptr() as u64 % 16 == 0); - let bytes = vec8.into_boxed_slice(); - assert!(bytes.as_ptr() as u64 % 16 == 0); + let mut vec_align: Vec = Vec::with_capacity(count_align); + vec_align.resize(count_align, 0); + let (buf, _len, _capacity) = vec_align.into_raw_parts(); + vec_align = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; + + let bytes = vec_align.into_boxed_slice(); Ok(()).map_err(|_: ()| { // This results in an error that can happen non-deterministically, since the memory // available to the compiler can change between runs. Normally queries are always @@ -290,14 +287,15 @@ impl Allocation { ) -> Result, Err> { // Compute new pointer provenance, which also adjusts the bytes. // Realign the pointer - // println!("adjusting: {:?}, {:?}", self.align, self.bytes.len()); - let count128 = (self.bytes.len() / 16) + 1; - let mut vec128: Vec = Vec::with_capacity(count128); - vec128.resize(count128, 0); - let (buf, _len, _capacity) = vec128.into_raw_parts(); - let mut vec8: Vec = unsafe {Vec::from_raw_parts(buf as *mut u8, self.bytes.len(), self.bytes.len())}; - vec8[..self.bytes.len()].copy_from_slice(&self.bytes); - let mut bytes = vec8.into_boxed_slice(); + let align_usize: usize = self.align.bytes().try_into().unwrap(); + let count_align = ((self.bytes.len() / align_usize) + 1)*align_usize; + + let mut vec_align: Vec = Vec::with_capacity(count_align); + vec_align.resize(count_align, 0); + assert!(vec_align.as_ptr() as u64 % self.align.bytes() == 0); + + vec_align[..self.bytes.len()].copy_from_slice(&self.bytes); + let mut bytes = vec_align.into_boxed_slice(); let mut new_relocations = Vec::with_capacity(self.relocations.0.len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; @@ -310,7 +308,8 @@ impl Allocation { write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap(); new_relocations.push((offset, ptr_prov)); } - assert!(bytes.as_ptr() as u64 % 16 == 0); + assert!(bytes.as_ptr() as u64 % self.align.bytes() == 0); + // Create allocation. Ok(Allocation { bytes, From bca203e555db5b54cd90697f62b01f9b4b8a83fc Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Fri, 12 Aug 2022 00:08:44 +0000 Subject: [PATCH 09/24] redoing allocation bytes realignment -- still testing with miri --- .../src/mir/interpret/allocation.rs | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 43e7d52d8d4d4..b47553eed1ba5 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -210,13 +210,11 @@ impl Allocation { let slice: Cow<'a, [u8]> = slice.into(); let size = Size::from_bytes(slice.len()); let align_usize: usize = align.bytes().try_into().unwrap(); - let count_align = ((slice.len() / align_usize) + 1)*align_usize; - - let mut vec_align: Vec = Vec::with_capacity(count_align); - vec_align.resize(count_align, 0); - // TODO avoid excess initialization - let (buf, _len, _capacity) = vec_align.into_raw_parts(); - vec_align = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; + let layout = std::alloc::Layout::from_size_align(slice.len(), align_usize).unwrap(); + let vec_align = unsafe { + let buf = std::alloc::alloc(layout); + Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize()) + }; let mut bytes = vec_align.into_boxed_slice(); assert!(bytes.as_ptr() as u64 % align.bytes() == 0); @@ -242,29 +240,28 @@ impl Allocation { /// If `panic_on_fail` is true, this will never return `Err`. pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> { let align_usize: usize = align.bytes().try_into().unwrap(); - let count_align = ((size.bytes_usize() / align_usize) + 1)*align_usize; - - // TODO this one is supposed to handle allocation failure, so do so. - let mut vec_align: Vec = Vec::with_capacity(count_align); - vec_align.resize(count_align, 0); - let (buf, _len, _capacity) = vec_align.into_raw_parts(); - vec_align = unsafe {Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize())}; + let layout = std::alloc::Layout::from_size_align(size.bytes_usize(), align_usize).unwrap(); + let vec_align = unsafe { + // https://doc.rust-lang.org/nightly/std/alloc/trait.GlobalAlloc.html#tymethod.alloc + // std::alloc::alloc returns null to indicate an allocation failure: + // "Returning a null pointer indicates that either memory is exhausted + // or layout does not meet this allocator’s size or alignment constraints." + let buf = std::alloc::alloc(layout); + // Handle allocation failure. + if buf.is_null() { + if panic_on_fail { + panic!("Allocation::uninit called with panic_on_fail had allocation failure") + } + ty::tls::with(|tcx| { + tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation") + }); + Err(InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted))? + } + Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize()) + }; let bytes = vec_align.into_boxed_slice(); - Ok(()).map_err(|_: ()| { - // This results in an error that can happen non-deterministically, since the memory - // available to the compiler can change between runs. Normally queries are always - // deterministic. However, we can be non-deterministic here because all uses of const - // evaluation (including ConstProp!) will make compilation fail (via hard error - // or ICE) upon encountering a `MemoryExhausted` error. - if panic_on_fail { - panic!("Allocation::uninit called with panic_on_fail had allocation failure") - } - ty::tls::with(|tcx| { - tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation") - }); - InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) - })?; + assert!(bytes.as_ptr() as u64 % align.bytes() == 0); Ok(Allocation { bytes, relocations: Relocations::new(), @@ -292,7 +289,7 @@ impl Allocation { let mut vec_align: Vec = Vec::with_capacity(count_align); vec_align.resize(count_align, 0); - assert!(vec_align.as_ptr() as u64 % self.align.bytes() == 0); + assert!(vec_align.as_ptr() as usize % align_usize == 0); vec_align[..self.bytes.len()].copy_from_slice(&self.bytes); let mut bytes = vec_align.into_boxed_slice(); From 0ddff36b27c085f6e3cc296160b2771151bfe5dd Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Fri, 12 Aug 2022 17:52:37 +0000 Subject: [PATCH 10/24] allocation bytes alignment, and cleanup .gitmodules --- .gitmodules | 3 --- compiler/rustc_middle/src/mir/interpret/allocation.rs | 11 ++++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.gitmodules b/.gitmodules index 8fa7a8673ef37..cca60e337d2d8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,6 +41,3 @@ [submodule "library/backtrace"] path = library/backtrace url = https://github.com/rust-lang/backtrace-rs.git -[submodule "src/tools/miri/"] - url = https://github.com/emarteca/miri - branch = matt-alloc-hacks diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index b47553eed1ba5..a17f824609fa0 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -218,7 +218,7 @@ impl Allocation { let mut bytes = vec_align.into_boxed_slice(); assert!(bytes.as_ptr() as u64 % align.bytes() == 0); - bytes[..slice.len()].copy_from_slice(&slice); + bytes.copy_from_slice(&slice); Self { bytes, @@ -285,10 +285,11 @@ impl Allocation { // Compute new pointer provenance, which also adjusts the bytes. // Realign the pointer let align_usize: usize = self.align.bytes().try_into().unwrap(); - let count_align = ((self.bytes.len() / align_usize) + 1)*align_usize; - - let mut vec_align: Vec = Vec::with_capacity(count_align); - vec_align.resize(count_align, 0); + let layout = std::alloc::Layout::from_size_align(self.bytes.len(), align_usize).unwrap(); + let mut vec_align = unsafe { + let buf = std::alloc::alloc(layout); + Vec::from_raw_parts(buf as *mut u8, self.bytes.len(), self.bytes.len()) + }; assert!(vec_align.as_ptr() as usize % align_usize == 0); vec_align[..self.bytes.len()].copy_from_slice(&self.bytes); From a72a05725a9dffeef5709749ffb34923c8cb74ee Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Fri, 12 Aug 2022 21:18:23 +0000 Subject: [PATCH 11/24] double free detected in tcache 2: could not compile core in stage 1 compilation --- compiler/rustc_middle/src/lib.rs | 1 + .../src/mir/interpret/allocation.rs | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index a07285bc3e540..7541fba885cae 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -23,6 +23,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(maybe_uninit_write_slice)] #![feature(allocator_api)] #![feature(array_windows)] #![feature(assert_matches)] diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index a17f824609fa0..ed0343329ef0f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -7,6 +7,7 @@ use std::hash; use std::iter; use std::ops::{Deref, Range}; use std::ptr; +use std::mem::MaybeUninit; use rustc_ast::Mutability; use rustc_data_structures::intern::Interned; @@ -211,14 +212,15 @@ impl Allocation { let size = Size::from_bytes(slice.len()); let align_usize: usize = align.bytes().try_into().unwrap(); let layout = std::alloc::Layout::from_size_align(slice.len(), align_usize).unwrap(); - let vec_align = unsafe { + let bytes = unsafe { let buf = std::alloc::alloc(layout); - Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize()) + let mut uninit_bytes = Vec::from_raw_parts(buf as *mut MaybeUninit, slice.len(), slice.len()); + let mut boxed = Box::<[MaybeUninit]>::from_raw(&mut *uninit_bytes); + MaybeUninit::write_slice(&mut boxed, &slice); + boxed.assume_init() }; - let mut bytes = vec_align.into_boxed_slice(); assert!(bytes.as_ptr() as u64 % align.bytes() == 0); - bytes.copy_from_slice(&slice); Self { bytes, @@ -286,14 +288,15 @@ impl Allocation { // Realign the pointer let align_usize: usize = self.align.bytes().try_into().unwrap(); let layout = std::alloc::Layout::from_size_align(self.bytes.len(), align_usize).unwrap(); - let mut vec_align = unsafe { + let mut bytes = unsafe { let buf = std::alloc::alloc(layout); - Vec::from_raw_parts(buf as *mut u8, self.bytes.len(), self.bytes.len()) + let mut uninit_bytes = Vec::from_raw_parts(buf as *mut MaybeUninit, self.bytes.len(), self.bytes.len()); + let mut boxed = Box::<[MaybeUninit]>::from_raw(&mut *uninit_bytes); + MaybeUninit::write_slice(&mut boxed, &self.bytes); + boxed.assume_init() }; - assert!(vec_align.as_ptr() as usize % align_usize == 0); + assert!(bytes.as_ptr() as usize % align_usize == 0); - vec_align[..self.bytes.len()].copy_from_slice(&self.bytes); - let mut bytes = vec_align.into_boxed_slice(); let mut new_relocations = Vec::with_capacity(self.relocations.0.len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; From 04f29dc4cded87f38667f06a590b81b5ba522a12 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Fri, 12 Aug 2022 21:41:49 +0000 Subject: [PATCH 12/24] using slice directly, no intermediate vec --- compiler/rustc_middle/src/mir/interpret/allocation.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index ed0343329ef0f..8df37c4f9c1a1 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -214,8 +214,7 @@ impl Allocation { let layout = std::alloc::Layout::from_size_align(slice.len(), align_usize).unwrap(); let bytes = unsafe { let buf = std::alloc::alloc(layout); - let mut uninit_bytes = Vec::from_raw_parts(buf as *mut MaybeUninit, slice.len(), slice.len()); - let mut boxed = Box::<[MaybeUninit]>::from_raw(&mut *uninit_bytes); + let mut boxed = Box::<[MaybeUninit]>::from_raw(std::slice::from_raw_parts_mut(buf as *mut MaybeUninit, slice.len())); MaybeUninit::write_slice(&mut boxed, &slice); boxed.assume_init() }; @@ -290,8 +289,7 @@ impl Allocation { let layout = std::alloc::Layout::from_size_align(self.bytes.len(), align_usize).unwrap(); let mut bytes = unsafe { let buf = std::alloc::alloc(layout); - let mut uninit_bytes = Vec::from_raw_parts(buf as *mut MaybeUninit, self.bytes.len(), self.bytes.len()); - let mut boxed = Box::<[MaybeUninit]>::from_raw(&mut *uninit_bytes); + let mut boxed = Box::<[MaybeUninit]>::from_raw(std::slice::from_raw_parts_mut(buf as *mut MaybeUninit, self.bytes.len())); MaybeUninit::write_slice(&mut boxed, &self.bytes); boxed.assume_init() }; From 2fd760612a1b96135f9e2f4166842af27900d971 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Mon, 15 Aug 2022 16:52:16 +0000 Subject: [PATCH 13/24] removing miri submodule updates --- Cargo.lock | 1 - .../clippy_lints/src/crate_in_macro_def.rs | 4 +- .../clippy/clippy_lints/src/matches/mod.rs | 2 +- .../src/methods/suspicious_map.rs | 3 +- .../src/undocumented_unsafe_blocks.rs | 2 +- .../clippy/clippy_lints/src/utils/author.rs | 2 +- .../clippy/clippy_utils/src/hir_utils.rs | 4 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +- src/tools/rustc-workspace-hack/Cargo.toml | 8 +- src/tools/rustfmt/src/macros.rs | 98 +++++++------------ src/tools/x/src/main.rs | 6 +- 11 files changed, 52 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e13570834e8d..4fd08ddef8ca0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3554,7 +3554,6 @@ dependencies = [ "crossbeam-utils", "libc", "libz-sys", - "memchr", "proc-macro2", "quote", "rand_core 0.5.1", diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs index 454ec23388af9..f6ec8fe7edc19 100644 --- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -110,14 +110,14 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { fn is_crate_keyword(tt: &TokenTree) -> Option { if_chain! { - if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }, _) = tt; + if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }) = tt; if symbol.as_str() == "crate"; then { Some(*span) } else { None } } } fn is_token(tt: &TokenTree, kind: &TokenKind) -> bool { - if let TokenTree::Token(Token { kind: other, .. }, _) = tt { + if let TokenTree::Token(Token { kind: other, .. }) = tt { kind == other } else { false diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index e9e13aece18f6..b638f27160282 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -1112,7 +1112,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { let mut pos = 0usize; let mut iter = tokenize(&snip).map(|t| { let start = pos; - pos += t.len as usize; + pos += t.len; (t.kind, start..pos) }); diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs index 9c3375bf35e7d..18ded291915e1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs @@ -12,8 +12,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hi if_chain! { if is_trait_method(cx, count_recv, sym::Iterator); let closure = expr_or_init(cx, map_arg); - if let Some(def_id) = cx.tcx.hir().opt_local_def_id(closure.hir_id); - if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id); + if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(closure.hir_id); let closure_body = cx.tcx.hir().body(body_id); if !cx.typeck_results().expr_ty(&closure_body.value).is_unit(); then { diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index d2e675a783eaa..04f16fd2161c5 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -345,7 +345,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) -> if line.starts_with("/*") { let src = src[line_start..line_starts.last().unwrap().to_usize() - offset].trim_start(); let mut tokens = tokenize(src); - return src[..tokens.next().unwrap().len as usize] + return src[..tokens.next().unwrap().len] .to_ascii_uppercase() .contains("SAFETY:") && tokens.all(|t| t.kind == TokenKind::Whitespace); diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index c0726868f77e2..bbb04c9945a09 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -138,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for Author { fn check_item(cx: &LateContext<'_>, hir_id: HirId) { let hir = cx.tcx.hir(); - if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner()) { + if let Some(body_id) = hir.maybe_body_owned_by(hir_id) { check_node(cx, hir_id, |v| { v.expr(&v.bind("expr", &hir.body(body_id).value)); }); diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 1834e2a2de872..eaf260ddfb832 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -141,7 +141,7 @@ impl HirEqInterExpr<'_, '_, '_> { let mut left_pos = 0; let left = tokenize(&left) .map(|t| { - let end = left_pos + t.len as usize; + let end = left_pos + t.len; let s = &left[left_pos..end]; left_pos = end; (t, s) @@ -156,7 +156,7 @@ impl HirEqInterExpr<'_, '_, '_> { let mut right_pos = 0; let right = tokenize(&right) .map(|t| { - let end = right_pos + t.len as usize; + let end = right_pos + t.len; let s = &right[right_pos..end]; right_pos = end; (t, s) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 7493a8685dff8..34a1cdaf1d52a 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -968,7 +968,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' } }, ExprKind::Closure { .. } => { - let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id); + let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id(); for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) { let local_id = match capture.place.base { PlaceBase::Local(id) => id, @@ -1353,7 +1353,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool if is_integer_literal(e, value) { return true; } - let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id); + let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id)); if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) { return value == v; } diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 00281bf8f014a..22c2d28d9f693 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -71,7 +71,7 @@ features = [ ] [dependencies] -bstr = { version = "0.2.17", features = ["default"] } +bstr = { version = "0.2.13", features = ["default"] } byteorder = { version = "1", features = ['default', 'std'] } clap = { version = "3.1.1", features = ["derive", "clap_derive"]} curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } @@ -79,12 +79,8 @@ crossbeam-utils = { version = "0.8.0", features = ["nightly"] } libc = { version = "0.2.79", features = ["align"] } # Ensure default features of libz-sys, which are disabled in some scenarios. libz-sys = { version = "1.1.2" } - -# looks like the only user of deprecated `use_std` feature is `combine`, so this -# can be removed if/when https://github.com/Marwes/combine/pull/348 be merged and released. -memchr = { version = "2.5", features = ["std", "use_std"] } # same for regex -regex = { version = "1.5.6" } +regex = { version = "1.5.5" } proc-macro2 = { version = "1", features = ["default"] } quote = { version = "1", features = ["default"] } rand_core_0_5 = { package = "rand_core", version = "0.5.1", features = ["getrandom", "alloc", "std"] } diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 3a641fab5d647..f4b2bcf281577 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{ @@ -682,7 +682,7 @@ struct MacroArgParser { fn last_tok(tt: &TokenTree) -> Token { match *tt { - TokenTree::Token(ref t, _) => t.clone(), + TokenTree::Token(ref t) => t.clone(), TokenTree::Delimited(delim_span, delim, _) => Token { kind: TokenKind::CloseDelim(delim), span: delim_span.close, @@ -737,13 +737,10 @@ impl MacroArgParser { fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> { match iter.next() { - Some(TokenTree::Token( - Token { - kind: TokenKind::Ident(name, _), - .. - }, - _, - )) => { + Some(TokenTree::Token(Token { + kind: TokenKind::Ident(name, _), + .. + })) => { self.result.push(ParsedMacroArg { kind: MacroArgKind::MetaVariable(name, self.buf.clone()), }); @@ -780,30 +777,21 @@ impl MacroArgParser { } match tok { - TokenTree::Token( - Token { - kind: TokenKind::BinOp(BinOpToken::Plus), - .. - }, - _, - ) - | TokenTree::Token( - Token { - kind: TokenKind::Question, - .. - }, - _, - ) - | TokenTree::Token( - Token { - kind: TokenKind::BinOp(BinOpToken::Star), - .. - }, - _, - ) => { + TokenTree::Token(Token { + kind: TokenKind::BinOp(BinOpToken::Plus), + .. + }) + | TokenTree::Token(Token { + kind: TokenKind::Question, + .. + }) + | TokenTree::Token(Token { + kind: TokenKind::BinOp(BinOpToken::Star), + .. + }) => { break; } - TokenTree::Token(ref t, _) => { + TokenTree::Token(ref t) => { buffer.push_str(&pprust::token_to_string(t)); } _ => return None, @@ -871,13 +859,10 @@ impl MacroArgParser { while let Some(tok) = iter.next() { match tok { - TokenTree::Token( - Token { - kind: TokenKind::Dollar, - span, - }, - _, - ) => { + TokenTree::Token(Token { + kind: TokenKind::Dollar, + span, + }) => { // We always want to add a separator before meta variables. if !self.buf.is_empty() { self.add_separator(); @@ -890,16 +875,13 @@ impl MacroArgParser { span, }; } - TokenTree::Token( - Token { - kind: TokenKind::Colon, - .. - }, - _, - ) if self.is_meta_var => { + TokenTree::Token(Token { + kind: TokenKind::Colon, + .. + }) if self.is_meta_var => { self.add_meta_variable(&mut iter)?; } - TokenTree::Token(ref t, _) => self.update_buffer(t), + TokenTree::Token(ref t) => self.update_buffer(t), TokenTree::Delimited(_delimited_span, delimited, ref tts) => { if !self.buf.is_empty() { if next_space(&self.last_tok.kind) == SpaceState::Always { @@ -1141,15 +1123,12 @@ impl MacroParser { TokenTree::Token(..) => return None, TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d), }; - let args = TokenStream::new(vec![tok]); + let args = TokenStream::new(vec![(tok, Spacing::Joint)]); match self.toks.next()? { - TokenTree::Token( - Token { - kind: TokenKind::FatArrow, - .. - }, - _, - ) => {} + TokenTree::Token(Token { + kind: TokenKind::FatArrow, + .. + }) => {} _ => return None, } let (mut hi, body, whole_body) = match self.toks.next()? { @@ -1168,13 +1147,10 @@ impl MacroParser { ) } }; - if let Some(TokenTree::Token( - Token { - kind: TokenKind::Semi, - span, - }, - _, - )) = self.toks.look_ahead(0) + if let Some(TokenTree::Token(Token { + kind: TokenKind::Semi, + span, + })) = self.toks.look_ahead(0) { hi = span.hi(); self.toks.next(); diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs index 9187c3551d7de..57d548f313dae 100644 --- a/src/tools/x/src/main.rs +++ b/src/tools/x/src/main.rs @@ -41,9 +41,9 @@ fn python() -> &'static str { } else if python2 { PYTHON2 } else { - // Python was not found on path, so exit - eprintln!("Unable to find python in your PATH. Please check it is installed."); - process::exit(1); + // We would have returned early if we found that python is installed ... + // maybe this should panic with an error instead? + PYTHON } } From ab1a61f7abe3ea0c8f1eebb054ca315eb864696b Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Mon, 15 Aug 2022 17:00:50 +0000 Subject: [PATCH 14/24] removing miri submodule updates --- .../clippy_lints/src/crate_in_macro_def.rs | 4 +- .../clippy/clippy_lints/src/matches/mod.rs | 2 +- .../src/methods/suspicious_map.rs | 3 +- .../src/undocumented_unsafe_blocks.rs | 2 +- .../clippy/clippy_lints/src/utils/author.rs | 2 +- .../clippy/clippy_utils/src/hir_utils.rs | 4 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +- src/tools/rustc-workspace-hack/Cargo.toml | 8 +- src/tools/rustfmt/src/macros.rs | 98 ++++++++++++------- src/tools/x/src/main.rs | 6 +- 10 files changed, 81 insertions(+), 52 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs index f6ec8fe7edc19..454ec23388af9 100644 --- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -110,14 +110,14 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { fn is_crate_keyword(tt: &TokenTree) -> Option { if_chain! { - if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }) = tt; + if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }, _) = tt; if symbol.as_str() == "crate"; then { Some(*span) } else { None } } } fn is_token(tt: &TokenTree, kind: &TokenKind) -> bool { - if let TokenTree::Token(Token { kind: other, .. }) = tt { + if let TokenTree::Token(Token { kind: other, .. }, _) = tt { kind == other } else { false diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index b638f27160282..e9e13aece18f6 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -1112,7 +1112,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { let mut pos = 0usize; let mut iter = tokenize(&snip).map(|t| { let start = pos; - pos += t.len; + pos += t.len as usize; (t.kind, start..pos) }); diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs index 18ded291915e1..9c3375bf35e7d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs @@ -12,7 +12,8 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hi if_chain! { if is_trait_method(cx, count_recv, sym::Iterator); let closure = expr_or_init(cx, map_arg); - if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(closure.hir_id); + if let Some(def_id) = cx.tcx.hir().opt_local_def_id(closure.hir_id); + if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id); let closure_body = cx.tcx.hir().body(body_id); if !cx.typeck_results().expr_ty(&closure_body.value).is_unit(); then { diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 04f16fd2161c5..d2e675a783eaa 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -345,7 +345,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) -> if line.starts_with("/*") { let src = src[line_start..line_starts.last().unwrap().to_usize() - offset].trim_start(); let mut tokens = tokenize(src); - return src[..tokens.next().unwrap().len] + return src[..tokens.next().unwrap().len as usize] .to_ascii_uppercase() .contains("SAFETY:") && tokens.all(|t| t.kind == TokenKind::Whitespace); diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index bbb04c9945a09..c0726868f77e2 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -138,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for Author { fn check_item(cx: &LateContext<'_>, hir_id: HirId) { let hir = cx.tcx.hir(); - if let Some(body_id) = hir.maybe_body_owned_by(hir_id) { + if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner()) { check_node(cx, hir_id, |v| { v.expr(&v.bind("expr", &hir.body(body_id).value)); }); diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index eaf260ddfb832..1834e2a2de872 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -141,7 +141,7 @@ impl HirEqInterExpr<'_, '_, '_> { let mut left_pos = 0; let left = tokenize(&left) .map(|t| { - let end = left_pos + t.len; + let end = left_pos + t.len as usize; let s = &left[left_pos..end]; left_pos = end; (t, s) @@ -156,7 +156,7 @@ impl HirEqInterExpr<'_, '_, '_> { let mut right_pos = 0; let right = tokenize(&right) .map(|t| { - let end = right_pos + t.len; + let end = right_pos + t.len as usize; let s = &right[right_pos..end]; right_pos = end; (t, s) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 34a1cdaf1d52a..7493a8685dff8 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -968,7 +968,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' } }, ExprKind::Closure { .. } => { - let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id(); + let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id); for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) { let local_id = match capture.place.base { PlaceBase::Local(id) => id, @@ -1353,7 +1353,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool if is_integer_literal(e, value) { return true; } - let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id)); + let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id); if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) { return value == v; } diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 22c2d28d9f693..00281bf8f014a 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -71,7 +71,7 @@ features = [ ] [dependencies] -bstr = { version = "0.2.13", features = ["default"] } +bstr = { version = "0.2.17", features = ["default"] } byteorder = { version = "1", features = ['default', 'std'] } clap = { version = "3.1.1", features = ["derive", "clap_derive"]} curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } @@ -79,8 +79,12 @@ crossbeam-utils = { version = "0.8.0", features = ["nightly"] } libc = { version = "0.2.79", features = ["align"] } # Ensure default features of libz-sys, which are disabled in some scenarios. libz-sys = { version = "1.1.2" } + +# looks like the only user of deprecated `use_std` feature is `combine`, so this +# can be removed if/when https://github.com/Marwes/combine/pull/348 be merged and released. +memchr = { version = "2.5", features = ["std", "use_std"] } # same for regex -regex = { version = "1.5.5" } +regex = { version = "1.5.6" } proc-macro2 = { version = "1", features = ["default"] } quote = { version = "1", features = ["default"] } rand_core_0_5 = { package = "rand_core", version = "0.5.1", features = ["getrandom", "alloc", "std"] } diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index f4b2bcf281577..3a641fab5d647 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{ @@ -682,7 +682,7 @@ struct MacroArgParser { fn last_tok(tt: &TokenTree) -> Token { match *tt { - TokenTree::Token(ref t) => t.clone(), + TokenTree::Token(ref t, _) => t.clone(), TokenTree::Delimited(delim_span, delim, _) => Token { kind: TokenKind::CloseDelim(delim), span: delim_span.close, @@ -737,10 +737,13 @@ impl MacroArgParser { fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> { match iter.next() { - Some(TokenTree::Token(Token { - kind: TokenKind::Ident(name, _), - .. - })) => { + Some(TokenTree::Token( + Token { + kind: TokenKind::Ident(name, _), + .. + }, + _, + )) => { self.result.push(ParsedMacroArg { kind: MacroArgKind::MetaVariable(name, self.buf.clone()), }); @@ -777,21 +780,30 @@ impl MacroArgParser { } match tok { - TokenTree::Token(Token { - kind: TokenKind::BinOp(BinOpToken::Plus), - .. - }) - | TokenTree::Token(Token { - kind: TokenKind::Question, - .. - }) - | TokenTree::Token(Token { - kind: TokenKind::BinOp(BinOpToken::Star), - .. - }) => { + TokenTree::Token( + Token { + kind: TokenKind::BinOp(BinOpToken::Plus), + .. + }, + _, + ) + | TokenTree::Token( + Token { + kind: TokenKind::Question, + .. + }, + _, + ) + | TokenTree::Token( + Token { + kind: TokenKind::BinOp(BinOpToken::Star), + .. + }, + _, + ) => { break; } - TokenTree::Token(ref t) => { + TokenTree::Token(ref t, _) => { buffer.push_str(&pprust::token_to_string(t)); } _ => return None, @@ -859,10 +871,13 @@ impl MacroArgParser { while let Some(tok) = iter.next() { match tok { - TokenTree::Token(Token { - kind: TokenKind::Dollar, - span, - }) => { + TokenTree::Token( + Token { + kind: TokenKind::Dollar, + span, + }, + _, + ) => { // We always want to add a separator before meta variables. if !self.buf.is_empty() { self.add_separator(); @@ -875,13 +890,16 @@ impl MacroArgParser { span, }; } - TokenTree::Token(Token { - kind: TokenKind::Colon, - .. - }) if self.is_meta_var => { + TokenTree::Token( + Token { + kind: TokenKind::Colon, + .. + }, + _, + ) if self.is_meta_var => { self.add_meta_variable(&mut iter)?; } - TokenTree::Token(ref t) => self.update_buffer(t), + TokenTree::Token(ref t, _) => self.update_buffer(t), TokenTree::Delimited(_delimited_span, delimited, ref tts) => { if !self.buf.is_empty() { if next_space(&self.last_tok.kind) == SpaceState::Always { @@ -1123,12 +1141,15 @@ impl MacroParser { TokenTree::Token(..) => return None, TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d), }; - let args = TokenStream::new(vec![(tok, Spacing::Joint)]); + let args = TokenStream::new(vec![tok]); match self.toks.next()? { - TokenTree::Token(Token { - kind: TokenKind::FatArrow, - .. - }) => {} + TokenTree::Token( + Token { + kind: TokenKind::FatArrow, + .. + }, + _, + ) => {} _ => return None, } let (mut hi, body, whole_body) = match self.toks.next()? { @@ -1147,10 +1168,13 @@ impl MacroParser { ) } }; - if let Some(TokenTree::Token(Token { - kind: TokenKind::Semi, - span, - })) = self.toks.look_ahead(0) + if let Some(TokenTree::Token( + Token { + kind: TokenKind::Semi, + span, + }, + _, + )) = self.toks.look_ahead(0) { hi = span.hi(); self.toks.next(); diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs index 57d548f313dae..9187c3551d7de 100644 --- a/src/tools/x/src/main.rs +++ b/src/tools/x/src/main.rs @@ -41,9 +41,9 @@ fn python() -> &'static str { } else if python2 { PYTHON2 } else { - // We would have returned early if we found that python is installed ... - // maybe this should panic with an error instead? - PYTHON + // Python was not found on path, so exit + eprintln!("Unable to find python in your PATH. Please check it is installed."); + process::exit(1); } } From b87f5ef8541a6303d26f3ac43926dd2f7e0a4a4b Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Mon, 15 Aug 2022 17:16:12 +0000 Subject: [PATCH 15/24] removing miri submodule updates --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 33ef5610317fa..1a87926a312fc 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 33ef5610317fa1a214ea691bab0582c956c3f944 +Subproject commit 1a87926a312fca90033c03c2ece5257e960dd242 From cade1c1d8efab6e17ec743f0f4020d8a22825d9c Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Mon, 15 Aug 2022 17:46:16 +0000 Subject: [PATCH 16/24] going back to previous version of miri to match commit of rustc --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 1a87926a312fc..b938529fb8ed8 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 1a87926a312fca90033c03c2ece5257e960dd242 +Subproject commit b938529fb8ed8f7b5b374282ffc3ffa74c313111 From c31d4048cd07f4bca3b5996d69a0fb9ec534c277 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Mon, 5 Sep 2022 14:56:07 -0400 Subject: [PATCH 17/24] moving AllocBytes into a trait -- partially done --- .../rustc_const_eval/src/interpret/memory.rs | 4 +- .../src/mir/interpret/allocation.rs | 168 +++++++++++++++--- 2 files changed, 149 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 692c750fcd3dd..aa072a2acd348 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -520,9 +520,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Get the base address for the bytes in an `Allocation` specified by the /// `AllocID` passed in; error if no such allocation exists. - pub fn get_alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, Size> { + pub fn get_alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, usize> { let alloc = self.get_alloc_raw(id)?; - Ok(alloc.get_bytes_addr()) + Ok(alloc.expose_base_addr()) } /// Gives raw access to the `Allocation`, without bounds or alignment checks. diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 8df37c4f9c1a1..f7f5557526cf0 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -4,6 +4,7 @@ use std::borrow::Cow; use std::convert::{TryFrom, TryInto}; use std::fmt; use std::hash; +use std::hash::Hash; use std::iter; use std::ops::{Deref, Range}; use std::ptr; @@ -12,6 +13,7 @@ use std::mem::MaybeUninit; use rustc_ast::Mutability; use rustc_data_structures::intern::Interned; use rustc_data_structures::sorted_map::SortedMap; +// use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::DUMMY_SP; use rustc_target::abi::{Align, HasDataLayout, Size}; @@ -22,6 +24,110 @@ use super::{ }; use crate::ty; +/// Representation of a section of memory, starting at a particular +/// address and of a specified length. +/// This is how we represent bytes in an `Allocation` that can't be +/// owned, since they belong to a foreign process -- in particular, we +/// use this to store pointers to C memory passed back from C FFI calls +/// in Miri. +// TODO! ellen move this into Miri +// #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +// #[derive(TyEncodable, TyDecodable)] +// pub struct AddrAllocBytes { +// /// Address of the beginning of the bytes. +// pub addr: u64, +// /// Size of the type of the data being stored in these bytes. +// pub type_size: usize, +// /// Length of the bytes, in multiples of `type_size`; +// /// it's in a `RefCell` since it can change depending on how it's used +// /// in the program. UNSAFE +// pub len: std::cell::RefCell, +// } + +// impl AddrAllocBytes { +// /// Length of the bytes. +// pub fn total_len(&self) -> usize { +// self.type_size * *self.len.borrow() +// } +// } + +// // Satisfy the `Hash` and `HashStable` trait requirements; can't be automatically derived. +// impl hash::Hash for AddrAllocBytes { +// fn hash(&self, state: &mut H) { +// self.addr.hash(state); +// self.type_size.hash(state); +// } +// } +// impl HashStable for AddrAllocBytes { +// fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { +// self.addr.hash_stable(hcx, hasher); +// self.type_size.hash_stable(hcx, hasher); +// } +// } + +/// Types that can be used to represent the `bytes field of an `Allocation`. +// #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +// #[derive(TyEncodable, TyDecodable)] +// #[derive(HashStable)] +// pub enum AllocBytes { +// /// Owned, boxed slice of [u8]. +// Boxed(Box<[u8]>), +// /// Address, size of the type stored, and length of the allocation. +// /// This is used for representing pointers to bytes that belong to a +// /// foreign process (such as pointers into C memory, passed back to Rust +// /// through an FFI call). +// Addr(AddrAllocBytes), +// } + +pub trait AllocBytes: Clone + core::fmt::Debug + Eq + PartialEq + PartialOrd + Ord + core::hash::Hash { + fn get_len(&self) -> usize; + fn get_addr(&self) -> u64; + fn get_slice_from_range(&self, range: Range) -> &[u8]; + fn get_slice_from_range_mut<'a>(&'a mut self, range: Range) -> &'a mut [u8]; + fn add_ptr(&mut self, to_add: usize) -> *mut u8; + fn write_maybe_uninit_slice(boxed: &mut Box<[MaybeUninit]>, to_write: &Self); + fn hash_head_tail(&self, _byte_count: usize, _state: &mut H, _max_bytes_to_hash: usize) {} +} + +impl AllocBytes for Box<[u8]> { + + /// The length of the bytes. + fn get_len(&self) -> usize { + self.len() + } + + /// The real address of the bytes. + fn get_addr(&self) -> u64 { + self.as_ptr() as u64 + } + + /// Slice of the bytes, for a specified range. + fn get_slice_from_range(&self, range: Range) -> &[u8] { + &self[range] + } + + /// Mutable slice of the bytes, for a specified range. + fn get_slice_from_range_mut<'a>(&'a mut self, range: Range) -> &'a mut [u8] { + &mut self[range] + } + + /// Pointer addition to the base address of the bytes. + fn add_ptr(&mut self, to_add: usize) -> *mut u8 { + self.as_mut_ptr().wrapping_add(to_add) + } + + /// Write an `AllocBytes` to a boxed slice of `MaybeUninit` -- this serves to initialize + /// the elements in `boxed`, for the length of the `AllocBytes` passed in. + fn write_maybe_uninit_slice(boxed: &mut Box<[MaybeUninit]>, to_write: &Self) { + MaybeUninit::write_slice(boxed, &to_write); + } + + fn hash_head_tail(&self, _byte_count: usize, _state: &mut H, _max_bytes_to_hash: usize) { + self[.._max_bytes_to_hash].hash(_state); + self[_byte_count - _max_bytes_to_hash..].hash(_state); + } +} + /// This type represents an Allocation in the Miri/CTFE core engine. /// /// Its public API is rather low-level, working directly with allocation offsets and a custom error @@ -31,10 +137,10 @@ use crate::ty; // hashed. (see the `Hash` impl below for more details), so the impl is not derived. #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(HashStable)] -pub struct Allocation { +pub struct Allocation> { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. - bytes: Box<[u8]>, + bytes: Bytes, /// Maps from byte addresses to extra data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting @@ -72,14 +178,13 @@ impl hash::Hash for Allocation { fn hash(&self, state: &mut H) { // Partially hash the `bytes` buffer when it is large. To limit collisions with common // prefixes and suffixes, we hash the length and some slices of the buffer. - let byte_count = self.bytes.len(); + let byte_count = self.bytes.get_len(); if byte_count > MAX_HASHED_BUFFER_LEN { // Hash the buffer's length. byte_count.hash(state); - // And its head and tail. - self.bytes[..MAX_BYTES_TO_HASH].hash(state); - self.bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state); + // And its head and tail, if it is a Box<[u8]>. + self.bytes.hash_head_tail(byte_count, state, MAX_BYTES_TO_HASH); } else { self.bytes.hash(state); } @@ -201,8 +306,9 @@ impl AllocRange { } // The constructors are all without extra; the extra gets added by a machine hook later. -impl Allocation { +impl Allocation { /// Creates an allocation initialized by the given bytes + // TODO! ellen make this generic for bytes pub fn from_bytes<'a>( slice: impl Into>, align: Align, @@ -231,6 +337,25 @@ impl Allocation { } } + // pub fn from_raw_addr( + // addr: u64, + // type_size: usize, + // len: usize, + // align: Align, + // mutability: Mutability, + // ) -> Self { + // let addr_alloc_bytes = AddrAllocBytes { addr, type_size, len: std::cell::RefCell::new(len)}; + // let size = Size::from_bytes(addr_alloc_bytes.total_len()); + // Self { + // bytes: AllocBytes::Addr(addr_alloc_bytes), + // relocations: Relocations::new(), + // init_mask: InitMask::new(size, true), + // align, + // mutability, + // extra: (), + // } + // } + pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into>) -> Self { Allocation::from_bytes(slice, Align::ONE, Mutability::Not) } @@ -264,7 +389,7 @@ impl Allocation { let bytes = vec_align.into_boxed_slice(); assert!(bytes.as_ptr() as u64 % align.bytes() == 0); Ok(Allocation { - bytes, + bytes: bytes, relocations: Relocations::new(), init_mask: InitMask::new(size, false), align, @@ -277,6 +402,7 @@ impl Allocation { impl Allocation { /// Adjust allocation from the ones in tcx to a custom Machine instance /// with a different Provenance and Extra type. + // TODO! ellen make this generic for Bytes pub fn adjust_from_tcx( self, cx: &impl HasDataLayout, @@ -285,16 +411,16 @@ impl Allocation { ) -> Result, Err> { // Compute new pointer provenance, which also adjusts the bytes. // Realign the pointer + let align_usize: usize = self.align.bytes().try_into().unwrap(); - let layout = std::alloc::Layout::from_size_align(self.bytes.len(), align_usize).unwrap(); + let layout = std::alloc::Layout::from_size_align(self.bytes.get_len(), align_usize).unwrap(); let mut bytes = unsafe { let buf = std::alloc::alloc(layout); - let mut boxed = Box::<[MaybeUninit]>::from_raw(std::slice::from_raw_parts_mut(buf as *mut MaybeUninit, self.bytes.len())); - MaybeUninit::write_slice(&mut boxed, &self.bytes); + let mut boxed = Box::<[MaybeUninit]>::from_raw(std::slice::from_raw_parts_mut(buf as *mut MaybeUninit, self.bytes.get_len())); + AllocBytes::write_maybe_uninit_slice(&mut boxed, &self.bytes); boxed.assume_init() }; assert!(bytes.as_ptr() as usize % align_usize == 0); - let mut new_relocations = Vec::with_capacity(self.relocations.0.len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; @@ -311,7 +437,7 @@ impl Allocation { // Create allocation. Ok(Allocation { - bytes, + bytes: bytes, relocations: Relocations::from_presorted(new_relocations), init_mask: self.init_mask, align: self.align, @@ -324,7 +450,7 @@ impl Allocation { /// Raw accessors. Provide access to otherwise private bytes. impl Allocation { pub fn len(&self) -> usize { - self.bytes.len() + self.bytes.get_len() } pub fn size(&self) -> Size { @@ -336,7 +462,7 @@ impl Allocation { /// edges) at all. /// This must not be used for reads affecting the interpreter execution. pub fn inspect_with_uninit_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { - &self.bytes[range] + self.bytes.get_slice_from_range(range) } /// Returns the mask indicating which bytes are initialized. @@ -353,15 +479,15 @@ impl Allocation { /// Byte accessors. impl Allocation { /// Get the pointer of the [u8] of bytes. - pub fn get_bytes_addr(&self) -> Size { - Size::from_bytes(self.bytes.as_ptr() as u64) + pub fn expose_base_addr(&self) -> usize { + self.bytes.get_addr().try_into().unwrap() } /// This is the entirely abstraction-violating way to just grab the raw bytes without /// caring about relocations. It just deduplicates some code between `read_scalar` /// and `get_bytes_internal`. fn get_bytes_even_more_internal(&self, range: AllocRange) -> &[u8] { - &self.bytes[range.start.bytes_usize()..range.end().bytes_usize()] + self.bytes.get_slice_from_range(range.start.bytes_usize()..range.end().bytes_usize()) } /// The last argument controls whether we error out when there are uninitialized or pointer @@ -430,7 +556,7 @@ impl Allocation { self.mark_init(range, true); self.clear_relocations(cx, range)?; - Ok(&mut self.bytes[range.start.bytes_usize()..range.end().bytes_usize()]) + Ok(self.bytes.get_slice_from_range_mut(range.start.bytes_usize()..range.end().bytes_usize())) } /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory. @@ -442,8 +568,8 @@ impl Allocation { self.mark_init(range, true); self.clear_relocations(cx, range)?; - assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check - let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize()); + assert!(range.end().bytes_usize() <= self.bytes.get_len()); // need to do our own bounds-check + let begin_ptr = self.bytes.add_ptr(range.start.bytes_usize()); let len = range.end().bytes_usize() - range.start.bytes_usize(); Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len)) } From e99368031d90c9e7a4f1fc631c40e282acf5ef72 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Tue, 6 Sep 2022 20:14:35 -0400 Subject: [PATCH 18/24] more moving allocbytes into trait --- .../src/mir/interpret/allocation.rs | 87 +++++++++---------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index f7f5557526cf0..34ddbc5bc159f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -87,9 +87,27 @@ pub trait AllocBytes: Clone + core::fmt::Debug + Eq + PartialEq + PartialOrd + O fn add_ptr(&mut self, to_add: usize) -> *mut u8; fn write_maybe_uninit_slice(boxed: &mut Box<[MaybeUninit]>, to_write: &Self); fn hash_head_tail(&self, _byte_count: usize, _state: &mut H, _max_bytes_to_hash: usize) {} + fn adjust_to_align(self, _align: Align) -> Self { + self + } + fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self; + fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>(size: Size, _align: Align, handle_alloc_fail: F) -> Result>; } impl AllocBytes for Box<[u8]> { + + fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>(size: Size, _align: Align, handle_alloc_fail: F) -> Result> { + let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| { + handle_alloc_fail() + })?; + // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> + let bytes = unsafe { bytes.assume_init() }; + Ok(bytes) + } + + fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self { + Box::<[u8]>::from(slice.into()) + } /// The length of the bytes. fn get_len(&self) -> usize { @@ -306,7 +324,7 @@ impl AllocRange { } // The constructors are all without extra; the extra gets added by a machine hook later. -impl Allocation { +impl Allocation { /// Creates an allocation initialized by the given bytes // TODO! ellen make this generic for bytes pub fn from_bytes<'a>( @@ -314,18 +332,8 @@ impl Allocation { align: Align, mutability: Mutability, ) -> Self { - let slice: Cow<'a, [u8]> = slice.into(); - let size = Size::from_bytes(slice.len()); - let align_usize: usize = align.bytes().try_into().unwrap(); - let layout = std::alloc::Layout::from_size_align(slice.len(), align_usize).unwrap(); - let bytes = unsafe { - let buf = std::alloc::alloc(layout); - let mut boxed = Box::<[MaybeUninit]>::from_raw(std::slice::from_raw_parts_mut(buf as *mut MaybeUninit, slice.len())); - MaybeUninit::write_slice(&mut boxed, &slice); - boxed.assume_init() - }; - - assert!(bytes.as_ptr() as u64 % align.bytes() == 0); + let bytes = Bytes::from_bytes(slice, align); + let size = Size::from_bytes(bytes.get_len()); Self { bytes, @@ -365,29 +373,23 @@ impl Allocation { /// /// If `panic_on_fail` is true, this will never return `Err`. pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> { - let align_usize: usize = align.bytes().try_into().unwrap(); - let layout = std::alloc::Layout::from_size_align(size.bytes_usize(), align_usize).unwrap(); - let vec_align = unsafe { - // https://doc.rust-lang.org/nightly/std/alloc/trait.GlobalAlloc.html#tymethod.alloc - // std::alloc::alloc returns null to indicate an allocation failure: - // "Returning a null pointer indicates that either memory is exhausted - // or layout does not meet this allocator’s size or alignment constraints." - let buf = std::alloc::alloc(layout); - // Handle allocation failure. - if buf.is_null() { - if panic_on_fail { - panic!("Allocation::uninit called with panic_on_fail had allocation failure") - } - ty::tls::with(|tcx| { - tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation") - }); - Err(InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted))? - } - Vec::from_raw_parts(buf as *mut u8, size.bytes_usize(), size.bytes_usize()) + let handle_alloc_fail = || -> InterpError<'tcx> { + // This results in an error that can happen non-deterministically, since the memory + // available to the compiler can change between runs. Normally queries are always + // deterministic. However, we can be non-deterministic here because all uses of const + // evaluation (including ConstProp!) will make compilation fail (via hard error + // or ICE) upon encountering a `MemoryExhausted` error. + if panic_on_fail { + panic!("Allocation::uninit called with panic_on_fail had allocation failure") + } + ty::tls::with(|tcx| { + tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation") + }); + InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) }; - let bytes = vec_align.into_boxed_slice(); - assert!(bytes.as_ptr() as u64 % align.bytes() == 0); + let bytes = Bytes::uninit(size, align, handle_alloc_fail)?; + Ok(Allocation { bytes: bytes, relocations: Relocations::new(), @@ -399,7 +401,7 @@ impl Allocation { } } -impl Allocation { +impl Allocation { /// Adjust allocation from the ones in tcx to a custom Machine instance /// with a different Provenance and Extra type. // TODO! ellen make this generic for Bytes @@ -408,32 +410,23 @@ impl Allocation { cx: &impl HasDataLayout, extra: Extra, mut adjust_ptr: impl FnMut(Pointer) -> Result, Err>, - ) -> Result, Err> { + ) -> Result, Err> { // Compute new pointer provenance, which also adjusts the bytes. // Realign the pointer + let mut bytes = self.bytes.adjust_to_align(self.align); - let align_usize: usize = self.align.bytes().try_into().unwrap(); - let layout = std::alloc::Layout::from_size_align(self.bytes.get_len(), align_usize).unwrap(); - let mut bytes = unsafe { - let buf = std::alloc::alloc(layout); - let mut boxed = Box::<[MaybeUninit]>::from_raw(std::slice::from_raw_parts_mut(buf as *mut MaybeUninit, self.bytes.get_len())); - AllocBytes::write_maybe_uninit_slice(&mut boxed, &self.bytes); - boxed.assume_init() - }; - assert!(bytes.as_ptr() as usize % align_usize == 0); let mut new_relocations = Vec::with_capacity(self.relocations.0.len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; for &(offset, alloc_id) in self.relocations.iter() { let idx = offset.bytes_usize(); - let ptr_bytes = &mut bytes[idx..idx + ptr_size]; + let ptr_bytes = bytes.get_slice_from_range_mut(idx..idx + ptr_size);//&mut bytes[idx..idx + ptr_size]; let bits = read_target_uint(endian, ptr_bytes).unwrap(); let (ptr_prov, ptr_offset) = adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_parts(); write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap(); new_relocations.push((offset, ptr_prov)); } - assert!(bytes.as_ptr() as u64 % self.align.bytes() == 0); // Create allocation. Ok(Allocation { From 17ac36b5b18df3d050bb4ebb6fd65f5a681346ac Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Wed, 7 Sep 2022 13:51:04 -0400 Subject: [PATCH 19/24] allocbytes moved into a trait, implemented for `Box<[u8]>` as default --- .../src/mir/interpret/allocation.rs | 101 +++--------------- 1 file changed, 16 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 34ddbc5bc159f..e078b103acbaa 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -8,7 +8,6 @@ use std::hash::Hash; use std::iter; use std::ops::{Deref, Range}; use std::ptr; -use std::mem::MaybeUninit; use rustc_ast::Mutability; use rustc_data_structures::intern::Interned; @@ -24,76 +23,33 @@ use super::{ }; use crate::ty; -/// Representation of a section of memory, starting at a particular -/// address and of a specified length. -/// This is how we represent bytes in an `Allocation` that can't be -/// owned, since they belong to a foreign process -- in particular, we -/// use this to store pointers to C memory passed back from C FFI calls -/// in Miri. -// TODO! ellen move this into Miri -// #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -// #[derive(TyEncodable, TyDecodable)] -// pub struct AddrAllocBytes { -// /// Address of the beginning of the bytes. -// pub addr: u64, -// /// Size of the type of the data being stored in these bytes. -// pub type_size: usize, -// /// Length of the bytes, in multiples of `type_size`; -// /// it's in a `RefCell` since it can change depending on how it's used -// /// in the program. UNSAFE -// pub len: std::cell::RefCell, -// } - -// impl AddrAllocBytes { -// /// Length of the bytes. -// pub fn total_len(&self) -> usize { -// self.type_size * *self.len.borrow() -// } -// } - -// // Satisfy the `Hash` and `HashStable` trait requirements; can't be automatically derived. -// impl hash::Hash for AddrAllocBytes { -// fn hash(&self, state: &mut H) { -// self.addr.hash(state); -// self.type_size.hash(state); -// } -// } -// impl HashStable for AddrAllocBytes { -// fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { -// self.addr.hash_stable(hcx, hasher); -// self.type_size.hash_stable(hcx, hasher); -// } -// } - -/// Types that can be used to represent the `bytes field of an `Allocation`. -// #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -// #[derive(TyEncodable, TyDecodable)] -// #[derive(HashStable)] -// pub enum AllocBytes { -// /// Owned, boxed slice of [u8]. -// Boxed(Box<[u8]>), -// /// Address, size of the type stored, and length of the allocation. -// /// This is used for representing pointers to bytes that belong to a -// /// foreign process (such as pointers into C memory, passed back to Rust -// /// through an FFI call). -// Addr(AddrAllocBytes), -// } - +/// Functionality required for the bytes of an `Allocation`. pub trait AllocBytes: Clone + core::fmt::Debug + Eq + PartialEq + PartialOrd + Ord + core::hash::Hash { + /// The length of the bytes. fn get_len(&self) -> usize; - fn get_addr(&self) -> u64; + /// The address of the bytes. + fn expose_addr(&self) -> u64; + /// Get a slice of the bytes corresponding to a specified range. fn get_slice_from_range(&self, range: Range) -> &[u8]; + /// Mutable slice of the bytes corresponding to a specified range. fn get_slice_from_range_mut<'a>(&'a mut self, range: Range) -> &'a mut [u8]; + /// Add to the pointer of the head of the bytes, and return a mutable pointer to this location. fn add_ptr(&mut self, to_add: usize) -> *mut u8; - fn write_maybe_uninit_slice(boxed: &mut Box<[MaybeUninit]>, to_write: &Self); + /// Hash the head and tail of the bytes. + /// This is required to statisfy the `Hash` trait. fn hash_head_tail(&self, _byte_count: usize, _state: &mut H, _max_bytes_to_hash: usize) {} + /// Adjust the bytes to the specified alignment -- by default, this is a no-op. fn adjust_to_align(self, _align: Align) -> Self { self } + /// Create an `AllocBytes` from a slice of `u8`. fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self; + /// Create an uninitialized `AllocBytes` of the specified size and alignment; + /// call the callback error handler if there is an error in allocating the memory. fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>(size: Size, _align: Align, handle_alloc_fail: F) -> Result>; } +// Default `bytes` for `Allocation` is a `Box<[u8]>`. impl AllocBytes for Box<[u8]> { fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>(size: Size, _align: Align, handle_alloc_fail: F) -> Result> { @@ -115,7 +71,7 @@ impl AllocBytes for Box<[u8]> { } /// The real address of the bytes. - fn get_addr(&self) -> u64 { + fn expose_addr(&self) -> u64 { self.as_ptr() as u64 } @@ -134,12 +90,6 @@ impl AllocBytes for Box<[u8]> { self.as_mut_ptr().wrapping_add(to_add) } - /// Write an `AllocBytes` to a boxed slice of `MaybeUninit` -- this serves to initialize - /// the elements in `boxed`, for the length of the `AllocBytes` passed in. - fn write_maybe_uninit_slice(boxed: &mut Box<[MaybeUninit]>, to_write: &Self) { - MaybeUninit::write_slice(boxed, &to_write); - } - fn hash_head_tail(&self, _byte_count: usize, _state: &mut H, _max_bytes_to_hash: usize) { self[.._max_bytes_to_hash].hash(_state); self[_byte_count - _max_bytes_to_hash..].hash(_state); @@ -345,25 +295,6 @@ impl Allocation { } } - // pub fn from_raw_addr( - // addr: u64, - // type_size: usize, - // len: usize, - // align: Align, - // mutability: Mutability, - // ) -> Self { - // let addr_alloc_bytes = AddrAllocBytes { addr, type_size, len: std::cell::RefCell::new(len)}; - // let size = Size::from_bytes(addr_alloc_bytes.total_len()); - // Self { - // bytes: AllocBytes::Addr(addr_alloc_bytes), - // relocations: Relocations::new(), - // init_mask: InitMask::new(size, true), - // align, - // mutability, - // extra: (), - // } - // } - pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into>) -> Self { Allocation::from_bytes(slice, Align::ONE, Mutability::Not) } @@ -473,7 +404,7 @@ impl Allocation { impl Allocation { /// Get the pointer of the [u8] of bytes. pub fn expose_base_addr(&self) -> usize { - self.bytes.get_addr().try_into().unwrap() + self.bytes.expose_addr().try_into().unwrap() } /// This is the entirely abstraction-violating way to just grab the raw bytes without From 99f6708dc8dd91890bace05f3187d267a0953e83 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Thu, 8 Sep 2022 16:19:45 -0400 Subject: [PATCH 20/24] cleanup --- compiler/rustc_const_eval/src/interpret/memory.rs | 2 +- compiler/rustc_middle/src/mir/interpret/allocation.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 0e3ce85fc402d..9c80fbf3391b2 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -517,7 +517,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } - /// Get the base address for the bytes in an `Allocation` specified by the + /// Get the base address for the bytes in an `Allocation` specified by the /// `AllocID` passed in; error if no such allocation exists. pub fn get_alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, usize> { let alloc = self.get_alloc_raw(id)?; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 85d837dd3aa89..0a19124d293b3 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -12,7 +12,6 @@ use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::intern::Interned; use rustc_data_structures::sorted_map::SortedMap; -// use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::DUMMY_SP; use rustc_target::abi::{Align, HasDataLayout, Size}; From a12d111e9959739eb51fb6077f0c72eb1a2633cf Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Thu, 8 Sep 2022 17:28:54 -0400 Subject: [PATCH 21/24] cleanup --- .../src/mir/interpret/allocation.rs | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 0a19124d293b3..8d4c55b2134ef 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -23,7 +23,9 @@ use super::{ use crate::ty; /// Functionality required for the bytes of an `Allocation`. -pub trait AllocBytes: Clone + core::fmt::Debug + Eq + PartialEq + PartialOrd + Ord + core::hash::Hash { +pub trait AllocBytes: + Clone + core::fmt::Debug + Eq + PartialEq + PartialOrd + Ord + core::hash::Hash +{ /// The length of the bytes. fn get_len(&self) -> usize; /// The address of the bytes. @@ -36,25 +38,37 @@ pub trait AllocBytes: Clone + core::fmt::Debug + Eq + PartialEq + PartialOrd + O fn add_ptr(&mut self, to_add: usize) -> *mut u8; /// Hash the head and tail of the bytes. /// This is required to statisfy the `Hash` trait. - fn hash_head_tail(&self, _byte_count: usize, _state: &mut H, _max_bytes_to_hash: usize) {} + fn hash_head_tail( + &self, + _byte_count: usize, + _state: &mut H, + _max_bytes_to_hash: usize, + ) { + } /// Adjust the bytes to the specified alignment -- by default, this is a no-op. fn adjust_to_align(self, _align: Align) -> Self { self } /// Create an `AllocBytes` from a slice of `u8`. fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self; - /// Create an uninitialized `AllocBytes` of the specified size and alignment; + /// Create an uninitialized `AllocBytes` of the specified size and alignment; /// call the callback error handler if there is an error in allocating the memory. - fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>(size: Size, _align: Align, handle_alloc_fail: F) -> Result>; + fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>( + size: Size, + _align: Align, + handle_alloc_fail: F, + ) -> Result>; } // Default `bytes` for `Allocation` is a `Box<[u8]>`. impl AllocBytes for Box<[u8]> { - - fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>(size: Size, _align: Align, handle_alloc_fail: F) -> Result> { - let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| { - handle_alloc_fail() - })?; + fn uninit<'tcx, F: Fn() -> InterpError<'tcx>>( + size: Size, + _align: Align, + handle_alloc_fail: F, + ) -> Result> { + let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()) + .map_err(|_| handle_alloc_fail())?; // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> let bytes = unsafe { bytes.assume_init() }; Ok(bytes) @@ -63,7 +77,7 @@ impl AllocBytes for Box<[u8]> { fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self { Box::<[u8]>::from(slice.into()) } - + /// The length of the bytes. fn get_len(&self) -> usize { self.len() @@ -89,9 +103,14 @@ impl AllocBytes for Box<[u8]> { self.as_mut_ptr().wrapping_add(to_add) } - fn hash_head_tail(&self, _byte_count: usize, _state: &mut H, _max_bytes_to_hash: usize) { + fn hash_head_tail( + &self, + _byte_count: usize, + _state: &mut H, + _max_bytes_to_hash: usize, + ) { self[.._max_bytes_to_hash].hash(_state); - self[_byte_count - _max_bytes_to_hash..].hash(_state); + self[_byte_count - _max_bytes_to_hash..].hash(_state); } } @@ -280,7 +299,7 @@ impl AllocRange { // The constructors are all without extra; the extra gets added by a machine hook later. impl Allocation { /// Creates an allocation initialized by the given bytes - // TODO! ellen make this generic for bytes + // FIXME! ellen make this generic for bytes pub fn from_bytes<'a>( slice: impl Into>, align: Align, @@ -288,7 +307,7 @@ impl Allocation { ) -> Self { let bytes = Bytes::from_bytes(slice, align); let size = Size::from_bytes(bytes.get_len()); - + Self { bytes, provenance: ProvenanceMap::new(), @@ -322,7 +341,7 @@ impl Allocation { }); InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) }; - + let bytes = Bytes::uninit(size, align, handle_alloc_fail)?; Ok(Allocation { @@ -339,7 +358,7 @@ impl Allocation { impl Allocation { /// Adjust allocation from the ones in tcx to a custom Machine instance /// with a different Provenance and Extra type. - // TODO! ellen make this generic for Bytes + // FIXME! ellen make this generic for Bytes pub fn adjust_from_tcx( self, cx: &impl HasDataLayout, @@ -355,14 +374,14 @@ impl Allocation { let endian = cx.data_layout().endian; for &(offset, alloc_id) in self.provenance.iter() { let idx = offset.bytes_usize(); - let ptr_bytes = bytes.get_slice_from_range_mut(idx..idx + ptr_size);//&mut bytes[idx..idx + ptr_size]; + let ptr_bytes = bytes.get_slice_from_range_mut(idx..idx + ptr_size); //&mut bytes[idx..idx + ptr_size]; let bits = read_target_uint(endian, ptr_bytes).unwrap(); let (ptr_prov, ptr_offset) = adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_parts(); write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap(); new_provenance.push((offset, ptr_prov)); } - + // Create allocation. Ok(Allocation { bytes, @@ -461,7 +480,9 @@ impl Allocation { self.mark_init(range, true); self.clear_provenance(cx, range)?; - Ok(self.bytes.get_slice_from_range_mut(range.start.bytes_usize()..range.end().bytes_usize())) + Ok(self + .bytes + .get_slice_from_range_mut(range.start.bytes_usize()..range.end().bytes_usize())) } /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory. From f75649b09c1399aa048133926a5bb94bec60d3ad Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Wed, 14 Sep 2022 17:01:29 -0400 Subject: [PATCH 22/24] propagating Allocation Bytes type --- .../rustc_const_eval/src/interpret/machine.rs | 10 +++++-- .../rustc_const_eval/src/interpret/memory.rs | 30 +++++++++---------- .../rustc_const_eval/src/interpret/place.rs | 4 +-- .../src/mir/interpret/allocation.rs | 16 +++++----- .../rustc_middle/src/mir/interpret/mod.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 20 ++++++------- 6 files changed, 43 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 530e252b7c077..2fb2f47fa8ca0 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -14,7 +14,7 @@ use rustc_target::abi::Size; use rustc_target::spec::abi::Abi as CallAbi; use super::{ - AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, + AllocId, AllocRange, Allocation, AllocBytes, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, }; @@ -103,10 +103,13 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Extra data stored in every allocation. type AllocExtra: Debug + Clone + 'static; + /// Type for the bytes of the allocation. + type Bytes: AllocBytes + 'static; + /// Memory's allocation map type MemoryMap: AllocMap< AllocId, - (MemoryKind, Allocation), + (MemoryKind, Allocation), > + Default + Clone; @@ -322,7 +325,7 @@ pub trait Machine<'mir, 'tcx>: Sized { id: AllocId, alloc: Cow<'b, Allocation>, kind: Option>, - ) -> InterpResult<'tcx, Cow<'b, Allocation>>; + ) -> InterpResult<'tcx, Cow<'b, Allocation>>; fn eval_inline_asm( _ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -431,6 +434,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type AllocExtra = (); type FrameExtra = (); + type Bytes = Box<[u8]>; #[inline(always)] fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 9c80fbf3391b2..e3cc8727b813a 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ - alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx, + alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, }; @@ -112,16 +112,16 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// A reference to some allocation that was already bounds-checked for the given region /// and had the on-access machine hooks run. #[derive(Copy, Clone)] -pub struct AllocRef<'a, 'tcx, Prov, Extra> { - alloc: &'a Allocation, +pub struct AllocRef<'a, 'tcx, Prov, Extra, Bytes: AllocBytes = Box<[u8]>> { + alloc: &'a Allocation, range: AllocRange, tcx: TyCtxt<'tcx>, alloc_id: AllocId, } /// A reference to some allocation that was already bounds-checked for the given region /// and had the on-access machine hooks run. -pub struct AllocRefMut<'a, 'tcx, Prov, Extra> { - alloc: &'a mut Allocation, +pub struct AllocRefMut<'a, 'tcx, Prov, Extra, Bytes: AllocBytes = Box<[u8]>> { + alloc: &'a mut Allocation, range: AllocRange, tcx: TyCtxt<'tcx>, alloc_id: AllocId, @@ -475,7 +475,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, id: AllocId, is_write: bool, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { + ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) { Some(GlobalAlloc::Memory(mem)) => { // Memory of a constant or promoted or anonymous memory referenced by a static. @@ -531,7 +531,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn get_alloc_raw( &self, id: AllocId, - ) -> InterpResult<'tcx, &Allocation> { + ) -> InterpResult<'tcx, &Allocation> { // The error type of the inner closure here is somewhat funny. We have two // ways of "erroring": An actual error, or because we got a reference from // `get_global_alloc` that we can actually use directly without inserting anything anywhere. @@ -567,7 +567,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> { let align = M::enforce_alignment(self).then_some(align); let ptr_and_alloc = self.check_and_deref_ptr( ptr, @@ -610,7 +610,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn get_alloc_raw_mut( &mut self, id: AllocId, - ) -> InterpResult<'tcx, (&mut Allocation, &mut M)> { + ) -> InterpResult<'tcx, (&mut Allocation, &mut M)> { // We have "NLL problem case #3" here, which cannot be worked around without loss of // efficiency even for the common case where the key is in the map. // @@ -639,7 +639,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> { let parts = self.get_ptr_access(ptr, size, align)?; if let Some((alloc_id, offset, prov)) = parts { let tcx = *self.tcx; @@ -833,12 +833,12 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // Cannot be a closure because it is generic in `Prov`, `Extra`. - fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>( + // Cannot be a closure because it is generic in `Prov`, `Extra`, and `Bytes`. + fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'tcx>, allocs_to_print: &mut VecDeque, - alloc: &Allocation, + alloc: &Allocation, ) -> std::fmt::Result { for alloc_id in alloc.provenance().values().filter_map(|prov| prov.get_alloc_id()) { allocs_to_print.push_back(alloc_id); @@ -905,7 +905,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, } /// Reading and writing. -impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> { +impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> { /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar(&mut self, range: AllocRange, val: Scalar) -> InterpResult<'tcx> { let range = self.range.subrange(range); @@ -930,7 +930,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> { } } -impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> { +impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> { /// `range` is relative to this allocation reference, not the base of the allocation. pub fn read_scalar( &self, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index b328892906df2..4cebc84198717 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -339,7 +339,7 @@ where pub(super) fn get_place_alloc( &self, place: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> { assert!(!place.layout.is_unsized()); assert!(!place.meta.has_meta()); let size = place.layout.size; @@ -350,7 +350,7 @@ where pub(super) fn get_place_alloc_mut( &mut self, place: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> { assert!(!place.layout.is_unsized()); assert!(!place.meta.has_meta()); let size = place.layout.size; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 8d4c55b2134ef..9b30a907d36f1 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -395,7 +395,7 @@ impl Allocation { } /// Raw accessors. Provide access to otherwise private bytes. -impl Allocation { +impl Allocation { pub fn len(&self) -> usize { self.bytes.get_len() } @@ -424,7 +424,7 @@ impl Allocation { } /// Byte accessors. -impl Allocation { +impl Allocation { /// Get the pointer of the [u8] of bytes. pub fn expose_base_addr(&self) -> usize { self.bytes.expose_addr().try_into().unwrap() @@ -442,7 +442,7 @@ impl Allocation { /// on that. #[inline] pub fn get_bytes_unchecked(&self, range: AllocRange) -> &[u8] { - &self.bytes[range.start.bytes_usize()..range.end().bytes_usize()] + &self.bytes.get_slice_from_range(range.start.bytes_usize()..range.end().bytes_usize()) } /// Checks that these bytes are initialized, and then strip provenance (if possible) and return @@ -502,7 +502,7 @@ impl Allocation { } /// Reading and writing. -impl Allocation { +impl Allocation { /// Reads a *non-ZST* scalar. /// /// If `read_provenance` is `true`, this will also read provenance; otherwise (if the machine @@ -616,7 +616,7 @@ impl Allocation { } /// Provenance. -impl Allocation { +impl Allocation { /// Returns all provenance overlapping with the given pointer-offset pair. fn range_get_provenance(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Prov)] { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with @@ -731,7 +731,7 @@ pub struct AllocationProvenance { dest_provenance: Vec<(Size, Prov)>, } -impl Allocation { +impl Allocation { pub fn prepare_provenance_copy( &self, cx: &impl HasDataLayout, @@ -1238,7 +1238,7 @@ impl<'a> Iterator for InitChunkIter<'a> { } /// Uninitialized bytes. -impl Allocation { +impl Allocation { /// Checks whether the given range is entirely initialized. /// /// Returns `Ok(())` if it's initialized. Otherwise returns the range of byte @@ -1286,7 +1286,7 @@ impl InitMaskCompressed { } /// Transferring the initialization mask to other allocations. -impl Allocation { +impl Allocation { /// Creates a run-length encoding of the initialization mask; panics if range is empty. /// /// This is essentially a more space-efficient version of diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 0fc1217d57196..e6b9f2c491b9a 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -127,7 +127,7 @@ pub use self::error::{ pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar}; pub use self::allocation::{ - alloc_range, AllocRange, Allocation, ConstAllocation, InitChunk, InitChunkIter, InitMask, + alloc_range, AllocBytes, AllocRange, Allocation, ConstAllocation, InitChunk, InitChunkIter, InitMask, ProvenanceMap, }; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 88c16189f1dc6..543f0ef2e1464 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; use rustc_middle::mir::interpret::{ - read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc, Pointer, + read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc, Pointer, Provenance, }; use rustc_middle::mir::visit::Visitor; @@ -779,21 +779,21 @@ pub fn write_allocations<'tcx>( /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control /// characters or characters whose value is larger than 127) with a `.` /// This also prints provenance adequately. -pub fn display_allocation<'a, 'tcx, Prov, Extra>( +pub fn display_allocation<'a, 'tcx, Prov, Extra, Bytes: AllocBytes>( tcx: TyCtxt<'tcx>, - alloc: &'a Allocation, -) -> RenderAllocation<'a, 'tcx, Prov, Extra> { + alloc: &'a Allocation, +) -> RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> { RenderAllocation { tcx, alloc } } #[doc(hidden)] -pub struct RenderAllocation<'a, 'tcx, Prov, Extra> { +pub struct RenderAllocation<'a, 'tcx, Prov, Extra, Bytes: AllocBytes = Box<[u8]>> { tcx: TyCtxt<'tcx>, - alloc: &'a Allocation, + alloc: &'a Allocation, } -impl<'a, 'tcx, Prov: Provenance, Extra> std::fmt::Display - for RenderAllocation<'a, 'tcx, Prov, Extra> +impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display + for RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> { fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let RenderAllocation { tcx, alloc } = *self; @@ -837,9 +837,9 @@ fn write_allocation_newline( /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there /// is only one line). Note that your prefix should contain a trailing space as the lines are /// printed directly after it. -fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>( +fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( tcx: TyCtxt<'tcx>, - alloc: &Allocation, + alloc: &Allocation, w: &mut dyn std::fmt::Write, prefix: &str, ) -> std::fmt::Result { From 8db066fc2debe2bf3be0a01a1618cfcc8a862d59 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Wed, 9 Nov 2022 17:19:08 -0500 Subject: [PATCH 23/24] adding deref and derefmut to allocbytes, removing now unnecessary methods from trait --- .../rustc_const_eval/src/interpret/memory.rs | 24 +++-- .../src/mir/interpret/allocation.rs | 88 ++++++------------- 2 files changed, 43 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index e3cc8727b813a..16275a6df95e4 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -19,8 +19,9 @@ use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ - alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx, - InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, + alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, + GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, + Scalar, }; #[derive(Debug, PartialEq, Copy, Clone)] @@ -518,8 +519,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } /// Get the base address for the bytes in an `Allocation` specified by the - /// `AllocID` passed in; error if no such allocation exists. - pub fn get_alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, usize> { + /// `AllocID` passed in; error if no such allocation exists. The address will + /// be exposed (on the host system!). + /// + /// It is up to the caller to take sufficient care when using this address: + /// there could be provenance or uninit memory in there, and other memory + /// accesses could invalidate the exposed pointer. + pub fn expose_alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, usize> { let alloc = self.get_alloc_raw(id)?; Ok(alloc.expose_base_addr()) } @@ -567,7 +573,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> + { let align = M::enforce_alignment(self).then_some(align); let ptr_and_alloc = self.check_and_deref_ptr( ptr, @@ -639,7 +646,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> + { let parts = self.get_ptr_access(ptr, size, align)?; if let Some((alloc_id, offset, prov)) = parts { let tcx = *self.tcx; @@ -905,7 +913,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, } /// Reading and writing. -impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> { +impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> + AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> +{ /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar(&mut self, range: AllocRange, val: Scalar) -> InterpResult<'tcx> { let range = self.range.subrange(range); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 9b30a907d36f1..d797a757427de 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -6,7 +6,7 @@ use std::fmt; use std::hash; use std::hash::Hash; use std::iter; -use std::ops::{Deref, Range}; +use std::ops::{Deref, DerefMut, Range}; use std::ptr; use rustc_ast::Mutability; @@ -24,27 +24,18 @@ use crate::ty; /// Functionality required for the bytes of an `Allocation`. pub trait AllocBytes: - Clone + core::fmt::Debug + Eq + PartialEq + PartialOrd + Ord + core::hash::Hash + Clone + + core::fmt::Debug + + Eq + + PartialEq + + PartialOrd + + Ord + + core::hash::Hash + + Deref + + DerefMut { - /// The length of the bytes. - fn get_len(&self) -> usize; /// The address of the bytes. fn expose_addr(&self) -> u64; - /// Get a slice of the bytes corresponding to a specified range. - fn get_slice_from_range(&self, range: Range) -> &[u8]; - /// Mutable slice of the bytes corresponding to a specified range. - fn get_slice_from_range_mut<'a>(&'a mut self, range: Range) -> &'a mut [u8]; - /// Add to the pointer of the head of the bytes, and return a mutable pointer to this location. - fn add_ptr(&mut self, to_add: usize) -> *mut u8; - /// Hash the head and tail of the bytes. - /// This is required to statisfy the `Hash` trait. - fn hash_head_tail( - &self, - _byte_count: usize, - _state: &mut H, - _max_bytes_to_hash: usize, - ) { - } /// Adjust the bytes to the specified alignment -- by default, this is a no-op. fn adjust_to_align(self, _align: Align) -> Self { self @@ -78,40 +69,10 @@ impl AllocBytes for Box<[u8]> { Box::<[u8]>::from(slice.into()) } - /// The length of the bytes. - fn get_len(&self) -> usize { - self.len() - } - /// The real address of the bytes. fn expose_addr(&self) -> u64 { self.as_ptr() as u64 } - - /// Slice of the bytes, for a specified range. - fn get_slice_from_range(&self, range: Range) -> &[u8] { - &self[range] - } - - /// Mutable slice of the bytes, for a specified range. - fn get_slice_from_range_mut<'a>(&'a mut self, range: Range) -> &'a mut [u8] { - &mut self[range] - } - - /// Pointer addition to the base address of the bytes. - fn add_ptr(&mut self, to_add: usize) -> *mut u8 { - self.as_mut_ptr().wrapping_add(to_add) - } - - fn hash_head_tail( - &self, - _byte_count: usize, - _state: &mut H, - _max_bytes_to_hash: usize, - ) { - self[.._max_bytes_to_hash].hash(_state); - self[_byte_count - _max_bytes_to_hash..].hash(_state); - } } /// This type represents an Allocation in the Miri/CTFE core engine. @@ -164,13 +125,14 @@ impl hash::Hash for Allocation { fn hash(&self, state: &mut H) { // Partially hash the `bytes` buffer when it is large. To limit collisions with common // prefixes and suffixes, we hash the length and some slices of the buffer. - let byte_count = self.bytes.get_len(); + let byte_count = self.bytes.len(); if byte_count > MAX_HASHED_BUFFER_LEN { // Hash the buffer's length. byte_count.hash(state); - // And its head and tail, if it is a Box<[u8]>. - self.bytes.hash_head_tail(byte_count, state, MAX_BYTES_TO_HASH); + // And its head and tail. + self.bytes[..MAX_BYTES_TO_HASH].hash(state); + self.bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state); } else { self.bytes.hash(state); } @@ -306,7 +268,7 @@ impl Allocation { mutability: Mutability, ) -> Self { let bytes = Bytes::from_bytes(slice, align); - let size = Size::from_bytes(bytes.get_len()); + let size = Size::from_bytes(bytes.len()); Self { bytes, @@ -318,6 +280,10 @@ impl Allocation { } } + // REEEEEEE TODO ELLEN + // make a new constructor that just takes a Bytes + // then, make the allocation this way in ffi_support, and add it to the memory with allocate_raw_ptr + pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into>) -> Self { Allocation::from_bytes(slice, Align::ONE, Mutability::Not) } @@ -374,7 +340,7 @@ impl Allocation { let endian = cx.data_layout().endian; for &(offset, alloc_id) in self.provenance.iter() { let idx = offset.bytes_usize(); - let ptr_bytes = bytes.get_slice_from_range_mut(idx..idx + ptr_size); //&mut bytes[idx..idx + ptr_size]; + let ptr_bytes = &mut bytes[idx..idx + ptr_size]; let bits = read_target_uint(endian, ptr_bytes).unwrap(); let (ptr_prov, ptr_offset) = adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_parts(); @@ -397,7 +363,7 @@ impl Allocation { /// Raw accessors. Provide access to otherwise private bytes. impl Allocation { pub fn len(&self) -> usize { - self.bytes.get_len() + self.bytes.len() } pub fn size(&self) -> Size { @@ -409,7 +375,7 @@ impl Allocation { /// edges) at all. /// This must not be used for reads affecting the interpreter execution. pub fn inspect_with_uninit_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { - self.bytes.get_slice_from_range(range) + &self.bytes[range] } /// Returns the mask indicating which bytes are initialized. @@ -442,7 +408,7 @@ impl Allocation /// on that. #[inline] pub fn get_bytes_unchecked(&self, range: AllocRange) -> &[u8] { - &self.bytes.get_slice_from_range(range.start.bytes_usize()..range.end().bytes_usize()) + &self.bytes[range.start.bytes_usize()..range.end().bytes_usize()] } /// Checks that these bytes are initialized, and then strip provenance (if possible) and return @@ -480,9 +446,7 @@ impl Allocation self.mark_init(range, true); self.clear_provenance(cx, range)?; - Ok(self - .bytes - .get_slice_from_range_mut(range.start.bytes_usize()..range.end().bytes_usize())) + Ok(&mut self.bytes[range.start.bytes_usize()..range.end().bytes_usize()]) } /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory. @@ -494,8 +458,8 @@ impl Allocation self.mark_init(range, true); self.clear_provenance(cx, range)?; - assert!(range.end().bytes_usize() <= self.bytes.get_len()); // need to do our own bounds-check - let begin_ptr = self.bytes.add_ptr(range.start.bytes_usize()); + assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check + let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize()); let len = range.end().bytes_usize() - range.start.bytes_usize(); Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len)) } From f075a124d72a8f76db30060d77c000cb6abf902c Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Wed, 9 Nov 2022 17:24:11 -0500 Subject: [PATCH 24/24] nit --- compiler/rustc_middle/src/mir/interpret/allocation.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index d797a757427de..b64f43aa6121e 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -37,9 +37,7 @@ pub trait AllocBytes: /// The address of the bytes. fn expose_addr(&self) -> u64; /// Adjust the bytes to the specified alignment -- by default, this is a no-op. - fn adjust_to_align(self, _align: Align) -> Self { - self - } + fn adjust_to_align(self, _align: Align) -> Self; /// Create an `AllocBytes` from a slice of `u8`. fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self; /// Create an uninitialized `AllocBytes` of the specified size and alignment; @@ -65,6 +63,10 @@ impl AllocBytes for Box<[u8]> { Ok(bytes) } + fn adjust_to_align(self, _align: Align) -> Self { + self + } + fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self { Box::<[u8]>::from(slice.into()) }