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
write!(f, "{:?}", tag.sb)
}
- fn get_alloc_id(self) -> AllocId {
- self.alloc_id
+ fn get_alloc_id(self) -> Option<AllocId> {
+ Some(self.alloc_id)
}
}
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>>,
/// 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> {
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,
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,
}
}
// 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())?;
}
#[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
}
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 {
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));
}
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
};
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)
}
#[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)]
(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())?;
}
tag,
range,
machine.stacked_borrows.as_ref().unwrap(),
+ &machine.threads,
)
} else {
Ok(())
(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())?;
}
tag,
range,
machine.stacked_borrows.as_ref().unwrap(),
+ &machine.threads,
)
} else {
Ok(())
(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));
}
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)]
#[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)]
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;
- }
-}