diff options
| author | Ralf Jung <post@ralfj.de> | 2022-04-18 10:00:42 -0400 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2022-04-18 10:14:06 -0400 |
| commit | c9e568f72e98ea4b754d3b318967f4d45534ab40 (patch) | |
| tree | 4910eb8869dad59ee0fc46174a8be8d1023c6ce7 | |
| parent | 54ab357a5b3041acf77cfcb99ddddadf945fe5aa (diff) | |
| download | rust-c9e568f72e98ea4b754d3b318967f4d45534ab40.tar.gz rust-c9e568f72e98ea4b754d3b318967f4d45534ab40.zip | |
avoid pairing up AllocId and PointerTag, which is redundant
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/machine.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/memory.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/pointer.rs | 3 |
3 files changed, 43 insertions, 23 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index ddfbcbdd22e..f386c7f36dc 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -88,6 +88,10 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to. type PointerTag: Provenance + Eq + Hash + 'static; + /// When getting the AllocId of a pointer, some extra data is also obtained from the tag + /// that is passed to memory access hooks so they can do things with it. + type TagExtra: Copy + 'static; + /// Machines can define extra (non-instance) things that represent values of function pointers. /// For example, Miri uses this to return a function pointer from `dlsym` /// that can later be called to execute the right thing. @@ -285,11 +289,14 @@ pub trait Machine<'mir, 'tcx>: Sized { addr: u64, ) -> Pointer<Option<Self::PointerTag>>; - /// Convert a pointer with provenance into an allocation-offset pair. + /// Convert a pointer with provenance into an allocation-offset pair + /// and extra provenance info. + /// + /// The returned `AllocId` must be the same as `ptr.provenance.get_alloc_id()`. fn ptr_get_alloc( ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer<Self::PointerTag>, - ) -> (AllocId, Size); + ) -> (AllocId, Size, Self::TagExtra); /// Called to initialize the "extra" state of an allocation and make the pointers /// it contains (in relocations) tagged. The way we construct allocations is @@ -321,7 +328,7 @@ pub trait Machine<'mir, 'tcx>: Sized { _tcx: TyCtxt<'tcx>, _machine: &Self, _alloc_extra: &Self::AllocExtra, - _tag: Self::PointerTag, + _tag: (AllocId, Self::TagExtra), _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) @@ -333,7 +340,7 @@ pub trait Machine<'mir, 'tcx>: Sized { _tcx: TyCtxt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, - _tag: Self::PointerTag, + _tag: (AllocId, Self::TagExtra), _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) @@ -345,7 +352,7 @@ pub trait Machine<'mir, 'tcx>: Sized { _tcx: TyCtxt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, - _tag: Self::PointerTag, + _tag: (AllocId, Self::TagExtra), _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) @@ -397,6 +404,8 @@ pub trait Machine<'mir, 'tcx>: Sized { // (CTFE and ConstProp) use the same instance. Here, we share that code. pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type PointerTag = AllocId; + type TagExtra = (); + type ExtraFnVal = !; type MemoryMap = @@ -474,9 +483,12 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn ptr_get_alloc(_ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer<AllocId>) -> (AllocId, Size) { + fn ptr_get_alloc( + _ecx: &InterpCx<$mir, $tcx, Self>, + ptr: Pointer<AllocId>, + ) -> (AllocId, Size, Self::TagExtra) { // We know `offset` is relative to the allocation, so we can use `into_parts`. let (alloc_id, offset) = ptr.into_parts(); - (alloc_id, offset) + (alloc_id, offset, ()) } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 4de2f3b9abb..262a53fc215 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -330,7 +330,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { *self.tcx, &mut self.machine, &mut alloc.extra, - tag, + (alloc_id, tag), alloc_range(Size::ZERO, size), )?; @@ -350,7 +350,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer<Option<M::PointerTag>>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option<(AllocId, Size, M::PointerTag)>> { + ) -> InterpResult<'tcx, Option<(AllocId, Size, M::TagExtra)>> { let align = M::enforce_alignment(&self).then_some(align); self.check_and_deref_ptr( ptr, @@ -401,11 +401,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { size: Size, align: Option<Align>, msg: CheckInAllocMsg, - alloc_size: impl FnOnce( - AllocId, - Size, - M::PointerTag, - ) -> InterpResult<'tcx, (Size, Align, T)>, + alloc_size: impl FnOnce(AllocId, Size, M::TagExtra) -> InterpResult<'tcx, (Size, Align, T)>, ) -> InterpResult<'tcx, Option<T>> { fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> { if offset % align.bytes() == 0 { @@ -450,7 +446,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // we want the error to be about the bounds. if let Some(align) = align { if M::force_int_for_alignment_check(self) { - assert!(M::PointerTag::OFFSET_IS_ADDR, "ptr-to-int cast for align check should never fail"); + assert!( + M::PointerTag::OFFSET_IS_ADDR, + "ptr-to-int cast for align check should never fail" + ); let (_, addr) = ptr.into_parts(); // we checked that offset is absolute check_offset_align(addr.bytes(), align)?; } else { @@ -575,7 +574,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )?; if let Some((alloc_id, offset, tag, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - M::memory_read(*self.tcx, &self.machine, &alloc.extra, tag, range)?; + M::memory_read(*self.tcx, &self.machine, &alloc.extra, (alloc_id, tag), range)?; Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id })) } else { // Even in this branch we have to be sure that we actually access the allocation, in @@ -636,7 +635,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; let range = alloc_range(offset, size); - M::memory_written(tcx, machine, &mut alloc.extra, tag, range)?; + M::memory_written(tcx, machine, &mut alloc.extra, (alloc_id, tag), range)?; Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id })) } else { Ok(None) @@ -1014,7 +1013,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); - M::memory_read(*tcx, &self.machine, &src_alloc.extra, src_tag, src_range)?; + M::memory_read(*tcx, &self.machine, &src_alloc.extra, (src_alloc_id, src_tag), src_range)?; // We need the `dest` ptr for the next operation, so we get it now. // We already did the source checks and called the hooks so we are good to return early. let Some((dest_alloc_id, dest_offset, dest_tag)) = dest_parts else { @@ -1039,7 +1038,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Destination alloc preparations and access hooks. let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?; let dest_range = alloc_range(dest_offset, size * num_copies); - M::memory_written(*tcx, extra, &mut dest_alloc.extra, dest_tag, dest_range)?; + M::memory_written( + *tcx, + extra, + &mut dest_alloc.extra, + (dest_alloc_id, dest_tag), + dest_range, + )?; let dest_bytes = dest_alloc .get_bytes_mut_ptr(&tcx, dest_range) .map_err(|e| e.to_interp_error(dest_alloc_id))? @@ -1158,11 +1163,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn ptr_try_get_alloc_id( &self, ptr: Pointer<Option<M::PointerTag>>, - ) -> Result<(AllocId, Size, M::PointerTag), u64> { + ) -> Result<(AllocId, Size, M::TagExtra), u64> { match ptr.into_pointer_or_addr() { Ok(ptr) => { - let (alloc_id, offset) = M::ptr_get_alloc(self, ptr); - Ok((alloc_id, offset, ptr.provenance)) + let (alloc_id, offset, extra) = M::ptr_get_alloc(self, ptr); + Ok((alloc_id, offset, extra)) } Err(addr) => Err(addr.bytes()), } @@ -1173,7 +1178,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn ptr_get_alloc_id( &self, ptr: Pointer<Option<M::PointerTag>>, - ) -> InterpResult<'tcx, (AllocId, Size, M::PointerTag)> { + ) -> InterpResult<'tcx, (AllocId, Size, M::TagExtra)> { self.ptr_try_get_alloc_id(ptr).map_err(|offset| { err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into() }) diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 813c0912f53..5ad2f80f06d 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -163,6 +163,9 @@ pub struct Pointer<Tag = AllocId> { } static_assert_size!(Pointer, 16); +// `Option<Tag>` pointers are also passed around quite a bit +// (but not stored in permanent machine state). +static_assert_size!(Pointer<Option<AllocId>>, 16); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. |
