next_call_id: CallId,
/// Those call IDs corresponding to functions that are still running.
active_calls: FxHashSet<CallId>,
- /// The id to trace in this execution run
+ /// The pointer id to trace
tracked_pointer_tag: Option<PtrId>,
+ /// The call id to trace
+ tracked_call_id: Option<CallId>,
}
/// Memory extra state gives us interior mutable access to the global state.
pub type MemoryExtra = Rc<RefCell<GlobalState>>;
/// Utilities for initialization and ID generation
impl GlobalState {
- pub fn new(tracked_pointer_tag: Option<PtrId>) -> Self {
+ pub fn new(tracked_pointer_tag: Option<PtrId>, tracked_call_id: Option<CallId>) -> Self {
GlobalState {
next_ptr_id: NonZeroU64::new(1).unwrap(),
base_ptr_ids: FxHashMap::default(),
next_call_id: NonZeroU64::new(1).unwrap(),
active_calls: FxHashSet::default(),
tracked_pointer_tag,
+ tracked_call_id,
}
}
fn new_ptr(&mut self) -> PtrId {
let id = self.next_ptr_id;
+ if Some(id) == self.tracked_pointer_tag {
+ register_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(id));
+ }
self.next_ptr_id = NonZeroU64::new(id.get() + 1).unwrap();
id
}
pub fn new_call(&mut self) -> CallId {
let id = self.next_call_id;
trace!("new_call: Assigning ID {}", id);
+ if Some(id) == self.tracked_call_id {
+ register_diagnostic(NonHaltingDiagnostic::CreatedCallId(id));
+ }
assert!(self.active_calls.insert(id));
self.next_call_id = NonZeroU64::new(id.get() + 1).unwrap();
id
fn check_protector(item: &Item, tag: Option<Tag>, global: &GlobalState) -> InterpResult<'tcx> {
if let Tag::Tagged(id) = item.tag {
if Some(id) == global.tracked_pointer_tag {
- register_diagnostic(NonHaltingDiagnostic::PoppedTrackedPointerTag(item.clone()));
+ register_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(item.clone()));
}
}
if let Some(call) = item.protector {
// everything else off the stack, invalidating all previous pointers,
// and in particular, *all* raw pointers.
MemoryKind::Stack => (Tag::Tagged(extra.borrow_mut().new_ptr()), Permission::Unique),
- // Global memory can be referenced by global pointers from `tcx`.
+ // `Global` memory can be referenced by global pointers from `tcx`.
// Thus we call `global_base_ptr` such that the global pointers get the same tag
// as what we use here.
- // `Machine` is used for extern statics, and thus must also be listed here.
+ // `ExternStatic` is used for extern statics, and thus must also be listed here.
// `Env` we list because we can get away with precise tracking there.
// The base pointer is not unique, so the base permission is `SharedReadWrite`.
- MemoryKind::Machine(MiriMemoryKind::Global | MiriMemoryKind::Machine | MiriMemoryKind::Env) =>
+ MemoryKind::Machine(MiriMemoryKind::Global | MiriMemoryKind::ExternStatic | MiriMemoryKind::Tls | MiriMemoryKind::Env) =>
(extra.borrow_mut().global_base_ptr(id), Permission::SharedReadWrite),
// Everything else we handle entirely untagged for now.
// FIXME: experiment with more precise tracking.
// Cannot use `builtin_deref` because that reports *immutable* for `Box`,
// making it useless.
fn qualify(ty: ty::Ty<'_>, kind: RetagKind) -> Option<(RefKind, bool)> {
- match ty.kind {
+ match ty.kind() {
// References are simple.
ty::Ref(_, _, Mutability::Mut) => Some((
RefKind::Unique { two_phase: kind == RetagKind::TwoPhase },