@@ -950,3 +950,56 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
950
950
}
951
951
}
952
952
}
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