about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bootstrap/configure.py1
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs10
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs10
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs10
-rw-r--r--src/tools/miri/src/concurrency/thread.rs12
-rw-r--r--src/tools/miri/src/concurrency/weak_memory.rs10
-rw-r--r--src/tools/miri/src/diagnostics.rs4
-rw-r--r--src/tools/miri/src/eval.rs15
-rw-r--r--src/tools/miri/src/helpers.rs12
-rw-r--r--src/tools/miri/src/machine.rs16
-rw-r--r--src/tools/miri/src/shims/backtrace.rs2
-rw-r--r--src/tools/miri/src/shims/env.rs2
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs2
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs2
-rw-r--r--src/tools/miri/src/shims/os_str.rs8
-rw-r--r--src/tools/miri/src/shims/unix/android/dlsym.rs2
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs2
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs2
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs4
-rw-r--r--src/tools/miri/src/shims/unix/macos/dlsym.rs2
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/windows/dlsym.rs2
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs4
-rw-r--r--src/tools/miri/src/tag_gc.rs39
-rw-r--r--src/tools/opt-dist/src/environment/windows.rs12
-rw-r--r--src/tools/opt-dist/src/utils/mod.rs19
26 files changed, 117 insertions, 93 deletions
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 15e8c1eb9f8..f469dbea6db 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -58,6 +58,7 @@ o("clang", "llvm.clang", "build clang")
 o("missing-tools", "dist.missing-tools", "allow failures when building tools")
 o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
 o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")
+o("patch-binaries-for-nix", "build.patch-binaries-for-nix", "whether patch binaries for usage with Nix toolchains")
 
 v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
 v("llvm-cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 0351f586872..a54bd32cd40 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -615,7 +615,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
     ) -> InterpResult<'tcx, Option<Provenance>> {
         let this = self.eval_context_mut();
         // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
-        this.check_ptr_access_align(place.ptr, size, Align::ONE, CheckInAllocMsg::InboundsTest)?;
+        this.check_ptr_access_align(place.ptr(), size, Align::ONE, CheckInAllocMsg::InboundsTest)?;
 
         // It is crucial that this gets called on all code paths, to ensure we track tag creation.
         let log_creation = |this: &MiriInterpCx<'mir, 'tcx>,
@@ -682,7 +682,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             trace!(
                 "reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
                 new_tag,
-                place.ptr,
+                place.ptr(),
                 place.layout.ty,
             );
             // Don't update any stacks for a zero-sized access; borrow stacks are per-byte and this
@@ -692,7 +692,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             // attempt to use it for a non-zero-sized access.
             // Dangling slices are a common case here; it's valid to get their length but with raw
             // pointer tagging for example all calls to get_unchecked on them are invalid.
-            if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr) {
+            if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr()) {
                 log_creation(this, Some((alloc_id, base_offset, orig_tag)))?;
                 // Still give it the new provenance, it got retagged after all.
                 return Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag }));
@@ -700,11 +700,11 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                 // This pointer doesn't come with an AllocId. :shrug:
                 log_creation(this, None)?;
                 // Provenance unchanged.
-                return Ok(place.ptr.provenance);
+                return Ok(place.ptr().provenance);
             }
         }
 
-        let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr)?;
+        let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr())?;
         log_creation(this, Some((alloc_id, base_offset, orig_tag)))?;
 
         trace!(
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index 08b138c68ae..8dd925a0ad8 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -172,7 +172,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         let this = self.eval_context_mut();
         // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
         this.check_ptr_access_align(
-            place.ptr,
+            place.ptr(),
             ptr_size,
             Align::ONE,
             CheckInAllocMsg::InboundsTest,
@@ -197,7 +197,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         };
 
         trace!("Reborrow of size {:?}", ptr_size);
-        let (alloc_id, base_offset, parent_prov) = match this.ptr_try_get_alloc_id(place.ptr) {
+        let (alloc_id, base_offset, parent_prov) = match this.ptr_try_get_alloc_id(place.ptr()) {
             Ok(data) => {
                 // Unlike SB, we *do* a proper retag for size 0 if can identify the allocation.
                 // After all, the pointer may be lazily initialized outside this initial range.
@@ -210,18 +210,18 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                 trace!(
                     "reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
                     new_tag,
-                    place.ptr,
+                    place.ptr(),
                     place.layout.ty,
                 );
                 log_creation(this, None)?;
                 // Keep original provenance.
-                return Ok(place.ptr.provenance);
+                return Ok(place.ptr().provenance);
             }
         };
         log_creation(this, Some((alloc_id, base_offset, parent_prov)))?;
 
         let orig_tag = match parent_prov {
-            ProvenanceExtra::Wildcard => return Ok(place.ptr.provenance), // TODO: handle wildcard pointers
+            ProvenanceExtra::Wildcard => return Ok(place.ptr().provenance), // TODO: handle wildcard pointers
             ProvenanceExtra::Concrete(tag) => tag,
         };
 
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 37125337d6f..513cec1f6c3 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -1018,7 +1018,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         // be 8-aligned).
         let align = Align::from_bytes(place.layout.size.bytes()).unwrap();
         this.check_ptr_access_align(
-            place.ptr,
+            place.ptr(),
             place.layout.size,
             align,
             CheckInAllocMsg::MemoryAccessTest,
@@ -1031,7 +1031,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         // We avoid `get_ptr_alloc` since we do *not* want to run the access hooks -- the actual
         // access will happen later.
         let (alloc_id, _offset, _prov) =
-            this.ptr_try_get_alloc_id(place.ptr).expect("there are no zero-sized atomic accesses");
+            this.ptr_try_get_alloc_id(place.ptr()).expect("there are no zero-sized atomic accesses");
         if this.get_alloc_mutability(alloc_id)? == Mutability::Not {
             // FIXME: make this prettier, once these messages have separate title/span/help messages.
             throw_ub_format!(
@@ -1135,7 +1135,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         if let Some(data_race) = &this.machine.data_race {
             if data_race.race_detecting() {
                 let size = place.layout.size;
-                let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr)?;
+                let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr())?;
                 // Load and log the atomic operation.
                 // Note that atomic loads are possible even from read-only allocations, so `get_alloc_extra_mut` is not an option.
                 let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap();
@@ -1143,7 +1143,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                     "Atomic op({}) with ordering {:?} on {:?} (size={})",
                     description,
                     &atomic,
-                    place.ptr,
+                    place.ptr(),
                     size.bytes()
                 );
 
@@ -1186,7 +1186,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                     {
                         log::trace!(
                             "Updated atomic memory({:?}, size={}) to {:#?}",
-                            place.ptr,
+                            place.ptr(),
                             size.bytes(),
                             mem_clocks.atomic_ops
                         );
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 9c11ad85aef..295d86fd240 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -8,6 +8,7 @@ use std::task::Poll;
 use std::time::{Duration, SystemTime};
 
 use log::trace;
+use either::Either;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
@@ -259,8 +260,15 @@ impl VisitTags for Frame<'_, '_, Provenance, FrameExtra<'_>> {
         return_place.visit_tags(visit);
         // Locals.
         for local in locals.iter() {
-            if let LocalValue::Live(value) = &local.value {
-                value.visit_tags(visit);
+            match local.as_mplace_or_imm() {
+                None => {}
+                Some(Either::Left((ptr, meta))) => {
+                    ptr.visit_tags(visit);
+                    meta.visit_tags(visit);
+                }
+                Some(Either::Right(imm)) => {
+                    imm.visit_tags(visit);
+                }
             }
         }
 
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index c1395468fee..6781b1f6dd3 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -481,7 +481,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         place: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
-        let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
+        let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
         if let crate::AllocExtra {
             weak_memory: Some(alloc_buffers),
             data_race: Some(alloc_clocks),
@@ -512,7 +512,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         init: Scalar<Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
+        let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
         if let (
             crate::AllocExtra { weak_memory: Some(alloc_buffers), .. },
             crate::MiriMachine { data_race: Some(global), threads, .. },
@@ -539,7 +539,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_ref();
         if let Some(global) = &this.machine.data_race {
-            let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
+            let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
             if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() {
                 if atomic == AtomicReadOrd::SeqCst {
                     global.sc_read(&this.machine.threads);
@@ -577,7 +577,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         init: Scalar<Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr)?;
+        let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr())?;
         if let (
             crate::AllocExtra { weak_memory: Some(alloc_buffers), .. },
             crate::MiriMachine { data_race: Some(global), threads, .. },
@@ -627,7 +627,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 global.sc_read(&this.machine.threads);
             }
             let size = place.layout.size;
-            let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
+            let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
             if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() {
                 let buffer = alloc_buffers
                     .get_or_create_store_buffer(alloc_range(base_offset, size), init)?;
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 298c5367522..4f249acda1d 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -376,9 +376,9 @@ pub fn report_error<'tcx, 'mir>(
     for (i, frame) in ecx.active_thread_stack().iter().enumerate() {
         trace!("-------------------");
         trace!("Frame {}", i);
-        trace!("    return: {:?}", *frame.return_place);
+        trace!("    return: {:?}", frame.return_place);
         for (i, local) in frame.locals.iter().enumerate() {
-            trace!("    local {}: {:?}", i, local.value);
+            trace!("    local {}: {:?}", i, local);
         }
     }
 
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 88e7d5386db..beb13ebdfe6 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -242,10 +242,7 @@ impl MainThreadState {
                 },
             Done => {
                 // Figure out exit code.
-                let ret_place = MPlaceTy::from_aligned_ptr(
-                    this.machine.main_fn_ret_place.unwrap().ptr,
-                    this.machine.layouts.isize,
-                );
+                let ret_place = this.machine.main_fn_ret_place.clone().unwrap();
                 let exit_code = this.read_target_isize(&ret_place)?;
                 // Need to call this ourselves since we are not going to return to the scheduler
                 // loop, and we want the main thread TLS to not show up as memory leaks.
@@ -308,7 +305,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
             let arg_type = Ty::new_array(tcx, tcx.types.u8, size);
             let arg_place =
                 ecx.allocate(ecx.layout_of(arg_type)?, MiriMemoryKind::Machine.into())?;
-            ecx.write_os_str_to_c_str(OsStr::new(arg), arg_place.ptr, size)?;
+            ecx.write_os_str_to_c_str(OsStr::new(arg), arg_place.ptr(), size)?;
             ecx.mark_immutable(&arg_place);
             argvs.push(arg_place.to_ref(&ecx));
         }
@@ -332,7 +329,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
                 ecx.allocate(ecx.machine.layouts.isize, MiriMemoryKind::Machine.into())?;
             ecx.write_scalar(argc, &argc_place)?;
             ecx.mark_immutable(&argc_place);
-            ecx.machine.argc = Some(*argc_place);
+            ecx.machine.argc = Some(argc_place.ptr());
 
             let argv_place = ecx.allocate(
                 ecx.layout_of(Ty::new_imm_ptr(tcx, tcx.types.unit))?,
@@ -340,7 +337,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
             )?;
             ecx.write_immediate(argv, &argv_place)?;
             ecx.mark_immutable(&argv_place);
-            ecx.machine.argv = Some(*argv_place);
+            ecx.machine.argv = Some(argv_place.ptr());
         }
         // Store command line as UTF-16 for Windows `GetCommandLineW`.
         {
@@ -351,7 +348,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
                 Ty::new_array(tcx, tcx.types.u16, u64::try_from(cmd_utf16.len()).unwrap());
             let cmd_place =
                 ecx.allocate(ecx.layout_of(cmd_type)?, MiriMemoryKind::Machine.into())?;
-            ecx.machine.cmd_line = Some(*cmd_place);
+            ecx.machine.cmd_line = Some(cmd_place.ptr());
             // Store the UTF-16 string. We just allocated so we know the bounds are fine.
             for (idx, &c) in cmd_utf16.iter().enumerate() {
                 let place = ecx.project_field(&cmd_place, idx)?;
@@ -364,7 +361,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
 
     // Return place (in static memory so that it does not count as leak).
     let ret_place = ecx.allocate(ecx.machine.layouts.isize, MiriMemoryKind::Machine.into())?;
-    ecx.machine.main_fn_ret_place = Some(*ret_place);
+    ecx.machine.main_fn_ret_place = Some(ret_place.clone());
     // Call start function.
 
     match entry_type {
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 844827889a7..0c7e8278147 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -381,7 +381,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Store how far we proceeded into the place so far. Everything to the left of
         // this offset has already been handled, in the sense that the frozen parts
         // have had `action` called on them.
-        let start_addr = place.ptr.addr();
+        let start_addr = place.ptr().addr();
         let mut cur_addr = start_addr;
         // Called when we detected an `UnsafeCell` at the given offset and size.
         // Calls `action` and advances `cur_ptr`.
@@ -413,7 +413,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let mut visitor = UnsafeCellVisitor {
                 ecx: this,
                 unsafe_cell_action: |place| {
-                    trace!("unsafe_cell_action on {:?}", place.ptr);
+                    trace!("unsafe_cell_action on {:?}", place.ptr());
                     // We need a size to go on.
                     let unsafe_cell_size = this
                         .size_and_align_of_mplace(place)?
@@ -422,7 +422,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         .unwrap_or_else(|| place.layout.size);
                     // Now handle this `UnsafeCell`, unless it is empty.
                     if unsafe_cell_size != Size::ZERO {
-                        unsafe_cell_action(&place.ptr, unsafe_cell_size)
+                        unsafe_cell_action(&place.ptr(), unsafe_cell_size)
                     } else {
                         Ok(())
                     }
@@ -432,7 +432,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
         // The part between the end_ptr and the end of the place is also frozen.
         // So pretend there is a 0-sized `UnsafeCell` at the end.
-        unsafe_cell_action(&place.ptr.offset(size, this)?, Size::ZERO)?;
+        unsafe_cell_action(&place.ptr().offset(size, this)?, Size::ZERO)?;
         // Done!
         return Ok(());
 
@@ -994,10 +994,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 
     /// Mark a machine allocation that was just created as immutable.
-    fn mark_immutable(&mut self, mplace: &MemPlace<Provenance>) {
+    fn mark_immutable(&mut self, mplace: &MPlaceTy<'tcx, Provenance>) {
         let this = self.eval_context_mut();
         // This got just allocated, so there definitely is a pointer here.
-        let provenance = mplace.ptr.into_pointer_or_addr().unwrap().provenance;
+        let provenance = mplace.ptr().into_pointer_or_addr().unwrap().provenance;
         this.alloc_mark_immutable(provenance.get_alloc_id().unwrap()).unwrap();
     }
 
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 9d01a04bf4a..80f83180448 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -396,14 +396,14 @@ pub struct MiriMachine<'mir, 'tcx> {
     pub(crate) env_vars: EnvVars<'tcx>,
 
     /// Return place of the main function.
-    pub(crate) main_fn_ret_place: Option<MemPlace<Provenance>>,
+    pub(crate) main_fn_ret_place: Option<MPlaceTy<'tcx, Provenance>>,
 
     /// Program arguments (`Option` because we can only initialize them after creating the ecx).
     /// These are *pointers* to argc/argv because macOS.
     /// We also need the full command line as one string because of Windows.
-    pub(crate) argc: Option<MemPlace<Provenance>>,
-    pub(crate) argv: Option<MemPlace<Provenance>>,
-    pub(crate) cmd_line: Option<MemPlace<Provenance>>,
+    pub(crate) argc: Option<Pointer<Option<Provenance>>>,
+    pub(crate) argv: Option<Pointer<Option<Provenance>>>,
+    pub(crate) cmd_line: Option<Pointer<Option<Provenance>>>,
 
     /// TLS state.
     pub(crate) tls: TlsData<'tcx>,
@@ -670,7 +670,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     ) -> InterpResult<'tcx> {
         let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
         this.write_immediate(*val, &place)?;
-        Self::add_extern_static(this, name, place.ptr);
+        Self::add_extern_static(this, name, place.ptr());
         Ok(())
     }
 
@@ -686,7 +686,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
                 Self::add_extern_static(
                     this,
                     "environ",
-                    this.machine.env_vars.environ.as_ref().unwrap().ptr,
+                    this.machine.env_vars.environ.as_ref().unwrap().ptr(),
                 );
                 // A couple zero-initialized pointer-sized extern statics.
                 // Most of them are for weak symbols, which we all set to null (indicating that the
@@ -703,7 +703,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
                 Self::add_extern_static(
                     this,
                     "environ",
-                    this.machine.env_vars.environ.as_ref().unwrap().ptr,
+                    this.machine.env_vars.environ.as_ref().unwrap().ptr(),
                 );
             }
             "android" => {
@@ -1415,7 +1415,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         local: mir::Local,
         mplace: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
-        let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr.provenance else {
+        let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr().provenance else {
             panic!("after_local_allocated should only be called on fresh allocations");
         };
         let local_decl = &ecx.active_thread_stack()[frame].body.local_decls[local];
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index a3297bf819f..c4c9f77fab7 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -89,7 +89,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
 
                 this.write_immediate(
-                    Immediate::new_slice(Scalar::from_maybe_pointer(alloc.ptr, this), len, this),
+                    Immediate::new_slice(Scalar::from_maybe_pointer(alloc.ptr(), this), len, this),
                     dest,
                 )?;
             }
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index 3694ea51da6..154a7f69833 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -459,7 +459,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let place = this.project_field(&vars_place, idx)?;
             this.write_pointer(var, &place)?;
         }
-        this.write_pointer(vars_place.ptr, &this.machine.env_vars.environ.clone().unwrap())?;
+        this.write_pointer(vars_place.ptr(), &this.machine.env_vars.environ.clone().unwrap())?;
 
         Ok(())
     }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 7996e72615f..47cbd4419f3 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -324,7 +324,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Second: functions that return immediately.
         match this.emulate_foreign_item_by_name(link_name, abi, args, dest)? {
             EmulateByNameResult::NeedsJumping => {
-                trace!("{:?}", this.dump_place(**dest));
+                trace!("{:?}", this.dump_place(dest));
                 this.go_to_block(ret);
             }
             EmulateByNameResult::AlreadyJumped => (),
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index 8a84b4f51b7..ef9d0710448 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -62,7 +62,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // The rest jumps to `ret` immediately.
         this.emulate_intrinsic_by_name(intrinsic_name, args, dest)?;
 
-        trace!("{:?}", this.dump_place(**dest));
+        trace!("{:?}", this.dump_place(dest));
         this.go_to_block(ret);
         Ok(())
     }
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index a94b1ddcd95..f6e76545a4d 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -143,9 +143,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let arg_type = Ty::new_array(this.tcx.tcx, this.tcx.types.u8, size);
         let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
-        let (written, _) = self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap();
+        let (written, _) = self.write_os_str_to_c_str(os_str, arg_place.ptr(), size).unwrap();
         assert!(written);
-        Ok(arg_place.ptr)
+        Ok(arg_place.ptr())
     }
 
     /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of `u16`.
@@ -160,9 +160,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let arg_type = Ty::new_array(this.tcx.tcx, this.tcx.types.u16, size);
         let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
         let (written, _) =
-            self.write_os_str_to_wide_str(os_str, arg_place.ptr, size, /*truncate*/ false).unwrap();
+            self.write_os_str_to_wide_str(os_str, arg_place.ptr(), size, /*truncate*/ false).unwrap();
         assert!(written);
-        Ok(arg_place.ptr)
+        Ok(arg_place.ptr())
     }
 
     /// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
diff --git a/src/tools/miri/src/shims/unix/android/dlsym.rs b/src/tools/miri/src/shims/unix/android/dlsym.rs
index b0c9d729c9d..451bc0bd5e1 100644
--- a/src/tools/miri/src/shims/unix/android/dlsym.rs
+++ b/src/tools/miri/src/shims/unix/android/dlsym.rs
@@ -47,7 +47,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
         }
 
-        log::trace!("{:?}", this.dump_place(**dest));
+        log::trace!("{:?}", this.dump_place(dest));
         this.go_to_block(ret);
         Ok(())
     }
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 3a480190535..865f01931f7 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -597,7 +597,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_pointer(buf, &pw_dir)?;
 
                 if written {
-                    this.write_pointer(pwd.ptr, &result)?;
+                    this.write_pointer(pwd.ptr(), &result)?;
                     this.write_null(dest)?;
                 } else {
                     this.write_null(&result)?;
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index dd2da3d22f2..8963dfb97a6 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -1439,7 +1439,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let file_name = dir_entry.file_name(); // not a Path as there are no separators!
                 let (name_fits, file_name_buf_len) = this.write_os_str_to_c_str(
                     &file_name,
-                    name_place.ptr,
+                    name_place.ptr(),
                     name_place.layout.size.bytes(),
                 )?;
                 let file_name_len = file_name_buf_len.checked_sub(1).unwrap();
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index 0474c9fd90a..7d15abfbfb2 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -35,7 +35,7 @@ pub fn futex<'tcx>(
     let thread = this.get_active_thread();
     // This is a vararg function so we have to bring our own type for this pointer.
     let addr = MPlaceTy::from_aligned_ptr(addr, this.machine.layouts.i32);
-    let addr_usize = addr.ptr.addr().bytes();
+    let addr_usize = addr.ptr().addr().bytes();
 
     let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG");
     let futex_wait = this.eval_libc_i32("FUTEX_WAIT");
@@ -90,7 +90,7 @@ pub fn futex<'tcx>(
                 &this.read_immediate(&args[3])?,
                 this.libc_ty_layout("timespec"),
             )?;
-            let timeout_time = if this.ptr_is_null(timeout.ptr)? {
+            let timeout_time = if this.ptr_is_null(timeout.ptr())? {
                 None
             } else {
                 let realtime = op & futex_realtime == futex_realtime;
diff --git a/src/tools/miri/src/shims/unix/macos/dlsym.rs b/src/tools/miri/src/shims/unix/macos/dlsym.rs
index 9177ecefe12..63ad680de60 100644
--- a/src/tools/miri/src/shims/unix/macos/dlsym.rs
+++ b/src/tools/miri/src/shims/unix/macos/dlsym.rs
@@ -45,7 +45,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
         }
 
-        trace!("{:?}", this.dump_place(**dest));
+        trace!("{:?}", this.dump_place(dest));
         this.go_to_block(ret);
         Ok(())
     }
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index f073daab8ed..3524fd70bcf 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -91,7 +91,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         .environ
                         .as_ref()
                         .expect("machine must be initialized")
-                        .ptr,
+                        .ptr(),
                     dest,
                 )?;
             }
@@ -113,14 +113,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "_NSGetArgc" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.write_pointer(
-                    this.machine.argc.expect("machine must be initialized").ptr,
+                    this.machine.argc.expect("machine must be initialized"),
                     dest,
                 )?;
             }
             "_NSGetArgv" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.write_pointer(
-                    this.machine.argv.expect("machine must be initialized").ptr,
+                    this.machine.argv.expect("machine must be initialized"),
                     dest,
                 )?;
             }
diff --git a/src/tools/miri/src/shims/windows/dlsym.rs b/src/tools/miri/src/shims/windows/dlsym.rs
index 7e2051fc98a..e5afee35905 100644
--- a/src/tools/miri/src/shims/windows/dlsym.rs
+++ b/src/tools/miri/src/shims/windows/dlsym.rs
@@ -75,7 +75,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
         }
 
-        trace!("{:?}", this.dump_place(**dest));
+        trace!("{:?}", this.dump_place(dest));
         this.go_to_block(ret);
         Ok(())
     }
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index cb90ed57ffe..28999268ba0 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -190,7 +190,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?;
                 // Initialize with `0`.
                 this.write_bytes_ptr(
-                    system_info.ptr,
+                    system_info.ptr(),
                     iter::repeat(0u8).take(system_info.layout.size.bytes_usize()),
                 )?;
                 // Set selected fields.
@@ -235,7 +235,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "GetCommandLineW" => {
                 let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.write_pointer(
-                    this.machine.cmd_line.expect("machine must be initialized").ptr,
+                    this.machine.cmd_line.expect("machine must be initialized"),
                     dest,
                 )?;
             }
diff --git a/src/tools/miri/src/tag_gc.rs b/src/tools/miri/src/tag_gc.rs
index cefdcc2b5b8..3cccdd36353 100644
--- a/src/tools/miri/src/tag_gc.rs
+++ b/src/tools/miri/src/tag_gc.rs
@@ -1,3 +1,5 @@
+use either::Either;
+
 use rustc_data_structures::fx::FxHashSet;
 
 use crate::*;
@@ -81,46 +83,33 @@ impl VisitTags for MemPlaceMeta<Provenance> {
     }
 }
 
-impl VisitTags for MemPlace<Provenance> {
+impl VisitTags for ImmTy<'_, Provenance> {
     fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
-        let MemPlace { ptr, meta } = self;
-        ptr.visit_tags(visit);
-        meta.visit_tags(visit);
+        (**self).visit_tags(visit)
     }
 }
 
 impl VisitTags for MPlaceTy<'_, Provenance> {
     fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
-        (**self).visit_tags(visit)
-    }
-}
-
-impl VisitTags for Place<Provenance> {
-    fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
-        match self {
-            Place::Ptr(p) => p.visit_tags(visit),
-            Place::Local { .. } => {
-                // Will be visited as part of the stack frame.
-            }
-        }
+        self.ptr().visit_tags(visit);
+        self.meta().visit_tags(visit);
     }
 }
 
 impl VisitTags for PlaceTy<'_, Provenance> {
     fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
-        (**self).visit_tags(visit)
+        match self.as_mplace_or_local() {
+            Either::Left(mplace) => mplace.visit_tags(visit),
+            Either::Right(_) => (),
+        }
     }
 }
 
-impl VisitTags for Operand<Provenance> {
+impl VisitTags for OpTy<'_, Provenance> {
     fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
-        match self {
-            Operand::Immediate(imm) => {
-                imm.visit_tags(visit);
-            }
-            Operand::Indirect(p) => {
-                p.visit_tags(visit);
-            }
+        match self.as_mplace_or_imm() {
+            Either::Left(mplace) => mplace.visit_tags(visit),
+            Either::Right(imm) => imm.visit_tags(visit),
         }
     }
 }
diff --git a/src/tools/opt-dist/src/environment/windows.rs b/src/tools/opt-dist/src/environment/windows.rs
index 67f63c7359d..79399391798 100644
--- a/src/tools/opt-dist/src/environment/windows.rs
+++ b/src/tools/opt-dist/src/environment/windows.rs
@@ -1,8 +1,10 @@
 use crate::environment::Environment;
 use crate::exec::cmd;
 use crate::utils::io::move_directory;
+use crate::utils::retry_action;
 use camino::Utf8PathBuf;
 use std::io::Cursor;
+use std::time::Duration;
 use zip::ZipArchive;
 
 pub(super) struct WindowsEnvironment {
@@ -43,7 +45,15 @@ impl Environment for WindowsEnvironment {
         const PERF_COMMIT: &str = "8b2ac3042e1ff2c0074455a0a3618adef97156b1";
 
         let url = format!("https://ci-mirrors.rust-lang.org/rustc/rustc-perf-{PERF_COMMIT}.zip");
-        let response = reqwest::blocking::get(url)?.error_for_status()?.bytes()?.to_vec();
+        let client = reqwest::blocking::Client::builder()
+            .timeout(Duration::from_secs(60 * 2))
+            .connect_timeout(Duration::from_secs(60 * 2))
+            .build()?;
+        let response = retry_action(
+            || Ok(client.get(&url).send()?.error_for_status()?.bytes()?.to_vec()),
+            "Download rustc-perf archive",
+            5,
+        )?;
 
         let mut archive = ZipArchive::new(Cursor::new(response))?;
         archive.extract(self.rustc_perf_dir())?;
diff --git a/src/tools/opt-dist/src/utils/mod.rs b/src/tools/opt-dist/src/utils/mod.rs
index 9a3df15e302..2af28077ed1 100644
--- a/src/tools/opt-dist/src/utils/mod.rs
+++ b/src/tools/opt-dist/src/utils/mod.rs
@@ -3,6 +3,7 @@ pub mod io;
 use crate::environment::Environment;
 use crate::utils::io::{delete_directory, get_files_from_dir};
 use humansize::{format_size, BINARY};
+use std::time::Duration;
 use sysinfo::{DiskExt, RefreshKind, System, SystemExt};
 
 pub fn format_env_variables() -> String {
@@ -70,6 +71,24 @@ pub fn with_log_group<F: FnOnce() -> R, R>(group: &str, func: F) -> R {
     }
 }
 
+#[allow(unused)]
+pub fn retry_action<F: Fn() -> anyhow::Result<R>, R>(
+    action: F,
+    name: &str,
+    count: u64,
+) -> anyhow::Result<R> {
+    for attempt in 0..count {
+        match action() {
+            Ok(result) => return Ok(result),
+            Err(error) => {
+                log::error!("Failed to perform action `{name}`, attempt #{attempt}: {error:?}");
+                std::thread::sleep(Duration::from_secs(5));
+            }
+        }
+    }
+    Err(anyhow::anyhow!("Failed to perform action `{name}` after {count} retries"))
+}
+
 fn is_in_ci() -> bool {
     std::env::var("GITHUB_ACTIONS").is_ok()
 }