Skip to content

Commit 840e323

Browse files
Add DFS iterator for Memory
1 parent f0148a5 commit 840e323

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

src/librustc_mir/interpret/memory.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,3 +950,56 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
950950
}
951951
}
952952
}
953+
954+
/// A depth-first search over the allocation graph.
955+
///
956+
/// This is based on the DFS in `rustc_data_structures`, which we cannot use directly because
957+
/// `AllocId` does not implement `Idx`.
958+
pub struct DepthFirstSearch<'mem, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
959+
memory: &'mem Memory<'mir, 'tcx, M>,
960+
visited: FxHashSet<AllocId>,
961+
stack: Vec<AllocId>,
962+
}
963+
964+
impl<M: Machine<'mir, 'tcx>> DepthFirstSearch<'mem, 'mir, 'tcx, M> {
965+
/// Returns a new DFS iterator that will traverse all allocations reachable from the given
966+
/// `AllocId`s.
967+
///
968+
/// The first node in `roots` will be the first node visited by the DFS.
969+
pub fn with_roots(
970+
memory: &'mem Memory<'mir, 'tcx, M>,
971+
roots: impl IntoIterator<Item = AllocId>,
972+
) -> Self {
973+
let mut stack: Vec<_> = roots.into_iter().collect();
974+
stack.reverse();
975+
976+
DepthFirstSearch {
977+
memory,
978+
visited: stack.iter().copied().collect(),
979+
stack,
980+
}
981+
}
982+
}
983+
984+
impl<M: Machine<'mir, 'tcx>> Iterator for DepthFirstSearch<'mem, 'mir, 'tcx, M> {
985+
type Item = (AllocId, InterpResult<'tcx, &'mem Allocation<M::PointerTag, M::AllocExtra>>);
986+
987+
fn next(&mut self) -> Option<Self::Item> {
988+
let DepthFirstSearch { stack, visited, memory } = self;
989+
990+
let id = stack.pop()?;
991+
let alloc = memory.get_raw(id);
992+
993+
if let Ok(alloc) = alloc {
994+
let new_pointers = alloc
995+
.relocations()
996+
.values()
997+
.map(|&(_, id)| id)
998+
.filter(|id| visited.insert(*id));
999+
1000+
stack.extend(new_pointers);
1001+
}
1002+
1003+
Some((id, alloc))
1004+
}
1005+
}

0 commit comments

Comments
 (0)