]> git.lizzy.rs Git - rust.git/blobdiff - src/machine.rs
rustup
[rust.git] / src / machine.rs
index 2fb5dca6dd68f442e235c926fa93a7d6c5a75f89..7ab15b9f9ceb61c78a9dfbd1603419fb4485fd70 100644 (file)
@@ -6,6 +6,7 @@
 use std::collections::HashSet;
 use std::fmt;
 use std::num::NonZeroU64;
+use std::rc::Rc;
 use std::time::Instant;
 
 use rand::rngs::StdRng;
     },
 };
 use rustc_span::def_id::{CrateNum, DefId};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::DUMMY_SP;
+use rustc_span::Symbol;
 use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
 
-use crate::*;
+use crate::{shims::posix::FileHandler, *};
 
 // Some global facts about the emulated machine.
 pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
@@ -159,8 +159,8 @@ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", tag.sb)
     }
 
-    fn get_alloc_id(self) -> AllocId {
-        self.alloc_id
+    fn get_alloc_id(self) -> Option<AllocId> {
+        Some(self.alloc_id)
     }
 }
 
@@ -274,7 +274,7 @@ pub struct Evaluator<'mir, 'tcx> {
     pub(crate) backtrace_style: BacktraceStyle,
 
     /// Crates which are considered local for the purposes of error reporting.
-    pub(crate) local_crates: Vec<CrateNum>,
+    pub(crate) local_crates: Rc<[CrateNum]>,
 
     /// Mapping extern static names to their base pointer.
     extern_statics: FxHashMap<Symbol, Pointer<Tag>>,
@@ -292,6 +292,9 @@ pub struct Evaluator<'mir, 'tcx> {
 
     /// Failure rate of compare_exchange_weak, between 0.0 and 1.0
     pub(crate) cmpxchg_weak_failure_rate: f64,
+
+    /// Corresponds to -Zmiri-mute-stdout-stderr and doesn't write the output but acts as if it succeeded.
+    pub(crate) mute_stdout_stderr: bool,
 }
 
 impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
@@ -328,7 +331,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
             validate: config.validate,
             enforce_number_validity: config.check_number_validity,
             enforce_abi: config.check_abi,
-            file_handler: Default::default(),
+            file_handler: FileHandler::new(config.mute_stdout_stderr),
             dir_handler: Default::default(),
             time_anchor: Instant::now(),
             layouts,
@@ -345,6 +348,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
             tracked_alloc_ids: config.tracked_alloc_ids.clone(),
             check_alignment: config.check_alignment,
             cmpxchg_weak_failure_rate: config.cmpxchg_weak_failure_rate,
+            mute_stdout_stderr: config.mute_stdout_stderr,
         }
     }
 
@@ -381,7 +385,8 @@ fn init_extern_statics(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'
                 // Most of them are for weak symbols, which we all set to null (indicating that the
                 // symbol is not supported, and triggering fallback code which ends up calling a
                 // syscall that we do support).
-                for name in &["__cxa_thread_atexit_impl", "getrandom", "statx"] {
+                for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
+                {
                     let layout = this.machine.layouts.usize;
                     let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
                     this.write_scalar(Scalar::from_machine_usize(0, this), &place.into())?;
@@ -465,7 +470,12 @@ fn enforce_validity(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
     }
 
     #[inline(always)]
-    fn enforce_number_validity(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
+    fn enforce_number_init(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
+        ecx.machine.enforce_number_validity
+    }
+
+    #[inline(always)]
+    fn enforce_number_no_provenance(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
         ecx.machine.enforce_number_validity
     }
 
@@ -544,11 +554,7 @@ fn extern_static_base_pointer(
         ecx: &MiriEvalContext<'mir, 'tcx>,
         def_id: DefId,
     ) -> InterpResult<'tcx, Pointer<Tag>> {
-        let attrs = ecx.tcx.get_attrs(def_id);
-        let link_name = match ecx.tcx.sess.first_attr_value_str_by_name(attrs, sym::link_name) {
-            Some(name) => name,
-            None => ecx.tcx.item_name(def_id),
-        };
+        let link_name = ecx.item_link_name(def_id);
         if let Some(&ptr) = ecx.machine.extern_statics.get(&link_name) {
             Ok(ptr)
         } else {
@@ -562,7 +568,6 @@ fn init_allocation_extra<'b>(
         alloc: Cow<'b, Allocation>,
         kind: Option<MemoryKind<Self::MemoryKind>>,
     ) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>> {
-        set_current_span(&ecx.machine);
         if ecx.machine.tracked_alloc_ids.contains(&id) {
             register_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id));
         }
@@ -570,7 +575,14 @@ fn init_allocation_extra<'b>(
         let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
         let alloc = alloc.into_owned();
         let stacks = if let Some(stacked_borrows) = &ecx.machine.stacked_borrows {
-            Some(Stacks::new_allocation(id, alloc.size(), stacked_borrows, kind))
+            Some(Stacks::new_allocation(
+                id,
+                alloc.size(),
+                stacked_borrows,
+                kind,
+                &ecx.machine.threads,
+                ecx.machine.local_crates.clone(),
+            ))
         } else {
             None
         };
@@ -591,7 +603,6 @@ fn tag_alloc_base_pointer(
         ecx: &MiriEvalContext<'mir, 'tcx>,
         ptr: Pointer<AllocId>,
     ) -> Pointer<Tag> {
-        set_current_span(&ecx.machine);
         let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr);
         let sb_tag = if let Some(stacked_borrows) = &ecx.machine.stacked_borrows {
             stacked_borrows.borrow_mut().base_tag(ptr.provenance)
@@ -602,21 +613,37 @@ fn tag_alloc_base_pointer(
     }
 
     #[inline(always)]
-    fn ptr_from_addr(
+    fn ptr_from_addr_cast(
         ecx: &MiriEvalContext<'mir, 'tcx>,
         addr: u64,
     ) -> Pointer<Option<Self::PointerTag>> {
         intptrcast::GlobalStateInner::ptr_from_addr(addr, ecx)
     }
 
+    #[inline(always)]
+    fn ptr_from_addr_transmute(
+        ecx: &MiriEvalContext<'mir, 'tcx>,
+        addr: u64,
+    ) -> Pointer<Option<Self::PointerTag>> {
+        Self::ptr_from_addr_cast(ecx, addr)
+    }
+
+    #[inline(always)]
+    fn expose_ptr(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _ptr: Pointer<Self::PointerTag>,
+    ) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
     /// Convert a pointer with provenance into an allocation-offset pair,
     /// or a `None` with an absolute address if that conversion is not possible.
     fn ptr_get_alloc(
         ecx: &MiriEvalContext<'mir, 'tcx>,
         ptr: Pointer<Self::PointerTag>,
-    ) -> (AllocId, Size, Self::TagExtra) {
+    ) -> Option<(AllocId, Size, Self::TagExtra)> {
         let rel = intptrcast::GlobalStateInner::abs_ptr_to_rel(ecx, ptr);
-        (ptr.provenance.alloc_id, rel, ptr.provenance.sb)
+        Some((ptr.provenance.alloc_id, rel, ptr.provenance.sb))
     }
 
     #[inline(always)]
@@ -627,7 +654,6 @@ fn memory_read(
         (alloc_id, tag): (AllocId, Self::TagExtra),
         range: AllocRange,
     ) -> InterpResult<'tcx> {
-        set_current_span(&machine);
         if let Some(data_race) = &alloc_extra.data_race {
             data_race.read(alloc_id, range, machine.data_race.as_ref().unwrap())?;
         }
@@ -637,6 +663,7 @@ fn memory_read(
                 tag,
                 range,
                 machine.stacked_borrows.as_ref().unwrap(),
+                &machine.threads,
             )
         } else {
             Ok(())
@@ -651,7 +678,6 @@ fn memory_written(
         (alloc_id, tag): (AllocId, Self::TagExtra),
         range: AllocRange,
     ) -> InterpResult<'tcx> {
-        set_current_span(&machine);
         if let Some(data_race) = &mut alloc_extra.data_race {
             data_race.write(alloc_id, range, machine.data_race.as_mut().unwrap())?;
         }
@@ -661,6 +687,7 @@ fn memory_written(
                 tag,
                 range,
                 machine.stacked_borrows.as_ref().unwrap(),
+                &machine.threads,
             )
         } else {
             Ok(())
@@ -675,7 +702,6 @@ fn memory_deallocated(
         (alloc_id, tag): (AllocId, Self::TagExtra),
         range: AllocRange,
     ) -> InterpResult<'tcx> {
-        set_current_span(&machine);
         if machine.tracked_alloc_ids.contains(&alloc_id) {
             register_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id));
         }
@@ -700,12 +726,7 @@ fn retag(
         kind: mir::RetagKind,
         place: &PlaceTy<'tcx, Tag>,
     ) -> InterpResult<'tcx> {
-        if ecx.machine.stacked_borrows.is_some() {
-            set_current_span(&ecx.machine);
-            ecx.retag(kind, place)
-        } else {
-            Ok(())
-        }
+        if ecx.machine.stacked_borrows.is_some() { ecx.retag(kind, place) } else { Ok(()) }
     }
 
     #[inline(always)]
@@ -751,12 +772,7 @@ fn stack_mut<'a>(
 
     #[inline(always)]
     fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
-        if ecx.machine.stacked_borrows.is_some() {
-            set_current_span(&ecx.machine);
-            ecx.retag_return_place()
-        } else {
-            Ok(())
-        }
+        if ecx.machine.stacked_borrows.is_some() { ecx.retag_return_place() } else { Ok(()) }
     }
 
     #[inline(always)]
@@ -773,30 +789,3 @@ fn after_stack_pop(
         res
     }
 }
-
-// This is potentially a performance hazard.
-// Factoring it into its own function lets us keep an eye on how much it shows up in a profile.
-///
-fn set_current_span<'mir, 'tcx: 'mir>(machine: &Evaluator<'mir, 'tcx>) {
-    if let Some(sb) = machine.stacked_borrows.as_ref() {
-        if sb.borrow().current_span != DUMMY_SP {
-            return;
-        }
-        let current_span = machine
-            .threads
-            .active_thread_stack()
-            .into_iter()
-            .rev()
-            .find(|frame| {
-                let info = FrameInfo {
-                    instance: frame.instance,
-                    span: frame.current_span(),
-                    lint_root: None,
-                };
-                machine.is_local(&info)
-            })
-            .map(|frame| frame.current_span())
-            .unwrap_or(rustc_span::DUMMY_SP);
-        sb.borrow_mut().current_span = current_span;
-    }
-}