From 9e239bdc764f8845b8959962cfaf654524a12b38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 16 Apr 2024 18:03:05 +0200 Subject: [PATCH] interpret: pass MemoryKind to adjust_alloc_base_pointer --- .../rustc_const_eval/src/interpret/machine.rs | 25 ++++++++++++------- .../rustc_const_eval/src/interpret/memory.rs | 10 ++++++-- src/tools/miri/src/alloc_addresses/mod.rs | 15 +++++++---- src/tools/miri/src/machine.rs | 6 +++-- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 3aeae5ebf6d..3e4be73e14f 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -301,15 +301,6 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { def_id: DefId, ) -> InterpResult<'tcx, Pointer>; - /// Return a "base" pointer for the given allocation: the one that is used for direct - /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. - /// - /// Not called on `extern` or thread-local statics (those use the methods above). - fn adjust_alloc_base_pointer( - ecx: &InterpCx<'mir, 'tcx, Self>, - ptr: Pointer, - ) -> InterpResult<'tcx, Pointer>; - /// "Int-to-pointer cast" fn ptr_from_addr_cast( ecx: &InterpCx<'mir, 'tcx, Self>, @@ -336,6 +327,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Called to adjust allocations to the Provenance and AllocExtra of this machine. /// + /// If `alloc` contains pointers, then they are all pointing to globals. + /// /// The way we construct allocations is to always first construct it without extra and then add /// the extra. This keeps uniform code paths for handling both allocations created by CTFE for /// globals, and allocations created by Miri during evaluation. @@ -354,6 +347,19 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { kind: Option>, ) -> InterpResult<'tcx, Cow<'b, Allocation>>; + /// Return a "root" pointer for the given allocation: the one that is used for direct + /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. + /// + /// Not called on `extern` or thread-local statics (those use the methods above). + /// + /// `kind` is the kind of the allocation the pointer points to; it can be `None` when + /// it's a global and `GLOBAL_KIND` is `None`. + fn adjust_alloc_base_pointer( + ecx: &InterpCx<'mir, 'tcx, Self>, + ptr: Pointer, + kind: Option>, + ) -> InterpResult<'tcx, Pointer>; + /// Evaluate the inline assembly. /// /// This should take care of jumping to the next block (one of `targets`) when asm goto @@ -604,6 +610,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { fn adjust_alloc_base_pointer( _ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer, + _kind: Option>, ) -> InterpResult<$tcx, Pointer> { Ok(ptr) } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index fbb0907f7d0..2820b062980 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -180,10 +180,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Some(GlobalAlloc::Static(def_id)) if self.tcx.is_foreign_item(def_id) => { return M::extern_static_base_pointer(self, def_id); } + None => { + assert!( + self.memory.extra_fn_ptr_map.contains_key(&alloc_id), + "{alloc_id:?} is neither global nor a function pointer" + ); + } _ => {} } // And we need to get the provenance. - M::adjust_alloc_base_pointer(self, ptr) + M::adjust_alloc_base_pointer(self, ptr, M::GLOBAL_KIND.map(MemoryKind::Machine)) } pub fn fn_ptr(&mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>) -> Pointer { @@ -240,7 +246,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); let alloc = M::adjust_allocation(self, id, Cow::Owned(alloc), Some(kind))?; self.memory.alloc_map.insert(id, (kind, alloc.into_owned())); - M::adjust_alloc_base_pointer(self, Pointer::from(id)) + M::adjust_alloc_base_pointer(self, Pointer::from(id), Some(kind)) } pub fn reallocate_ptr( diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index fec39ec2b8e..22f9a90a80a 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -141,7 +141,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn addr_from_alloc_id(&self, alloc_id: AllocId) -> InterpResult<'tcx, u64> { + fn addr_from_alloc_id( + &self, + alloc_id: AllocId, + _kind: MemoryKind, + ) -> InterpResult<'tcx, u64> { let ecx = self.eval_context_ref(); let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let global_state = &mut *global_state; @@ -283,16 +287,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Convert a relative (tcx) pointer to a Miri pointer. - fn ptr_from_rel_ptr( + fn adjust_alloc_base_pointer( &self, ptr: Pointer, tag: BorTag, + kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { let ecx = self.eval_context_ref(); let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) let alloc_id = prov.alloc_id(); - let base_addr = ecx.addr_from_alloc_id(alloc_id)?; + let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?; // Add offset with the right kind of pointer-overflowing arithmetic. let dl = ecx.data_layout(); @@ -314,9 +319,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ecx.alloc_id_from_addr(addr.bytes())? }; - // This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr + // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_base_pointer // must have been called in the past, so we can just look up the address in the map. - let base_addr = ecx.addr_from_alloc_id(alloc_id).unwrap(); + let base_addr = *ecx.machine.alloc_addresses.borrow().base_addr.get(&alloc_id).unwrap(); // Wrapping "addr - base_addr" #[allow(clippy::cast_possible_wrap)] // we want to wrap here diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 1d06d5c69d3..2bd1b24ee91 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1090,7 +1090,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { alloc: Cow<'b, Allocation>, kind: Option, ) -> InterpResult<'tcx, Cow<'b, Allocation>> { - let kind = kind.expect("we set our STATIC_KIND so this cannot be None"); + let kind = kind.expect("we set our GLOBAL_KIND so this cannot be None"); if ecx.machine.tracked_alloc_ids.contains(&id) { ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc( id, @@ -1151,7 +1151,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn adjust_alloc_base_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, + kind: Option, ) -> InterpResult<'tcx, Pointer> { + let kind = kind.expect("we set our GLOBAL_KIND so this cannot be None"); let alloc_id = ptr.provenance.alloc_id(); if cfg!(debug_assertions) { // The machine promises to never call us on thread-local or extern statics. @@ -1172,7 +1174,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { // Value does not matter, SB is disabled BorTag::default() }; - ecx.ptr_from_rel_ptr(ptr, tag) + ecx.adjust_alloc_base_pointer(ptr, tag, kind) } /// Called on `usize as ptr` casts.