@@ -1523,60 +1523,57 @@ pub(crate) mod convert {
15231523 use crate :: write:: {
15241524 self , ConvertError , ConvertLineProgram , ConvertResult , Dwarf , LocationList , RangeList ,
15251525 } ;
1526- use fnv:: { FnvHashMap as HashMap , FnvHashSet as HashSet } ;
1526+ use fnv:: FnvHashMap as HashMap ;
15271527
15281528 #[ derive( Debug , Default ) ]
15291529 struct FilterDependencies {
1530- edges : HashMap < UnitSectionOffset , HashSet < UnitSectionOffset > > ,
1531- required : HashSet < UnitSectionOffset > ,
1530+ edges : HashMap < UnitSectionOffset , Vec < UnitSectionOffset > > ,
1531+ required : Vec < UnitSectionOffset > ,
15321532 }
15331533
15341534 impl FilterDependencies {
15351535 /// Mark `entry` as a valid offset.
15361536 ///
15371537 /// This must be called before adding an edge from an entry.
1538- fn add_entry ( & mut self , entry : UnitSectionOffset ) {
1538+ ///
1539+ /// Also add edges from `entry` to `deps`.
1540+ fn add_entry ( & mut self , entry : UnitSectionOffset , deps : Vec < UnitSectionOffset > ) {
15391541 debug_assert ! ( !self . edges. contains_key( & entry) ) ;
1540- self . edges . insert ( entry, HashSet :: default ( ) ) ;
1542+ self . edges . insert ( entry, deps ) ;
15411543 }
15421544
15431545 /// If `from` is reachable then `to` is also reachable.
15441546 ///
15451547 /// Must have already called `add_entry(from)`.
15461548 ///
1547- /// The edge will be ignored if `add_entry(to) ` is never called
1549+ /// The edge will be ignored if `add_entry` is never called for `to`
15481550 /// (either before or after).
15491551 fn add_edge ( & mut self , from : UnitSectionOffset , to : UnitSectionOffset ) {
1550- self . edges . get_mut ( & from) . unwrap ( ) . insert ( to) ;
1552+ self . edges . get_mut ( & from) . unwrap ( ) . push ( to) ;
15511553 }
15521554
15531555 /// Mark `entry` as reachable.
15541556 ///
1555- /// This doesn't depend on `add_entry` being called for the entry
1556- /// (but you probably should at some stage anyway ).
1557+ /// The entry will be ignored if `add_entry` is never called for ` entry`
1558+ /// (either before or after ).
15571559 fn require_entry ( & mut self , entry : UnitSectionOffset ) {
1558- self . required . insert ( entry) ;
1560+ self . required . push ( entry) ;
15591561 }
15601562
15611563 /// Return a sorted list of all reachable entries.
1562- fn get_reachable ( self ) -> Vec < UnitSectionOffset > {
1563- let mut reachable = self . required . clone ( ) ;
1564- let mut queue = Vec :: new ( ) ;
1565- for i in self . required . iter ( ) {
1566- queue. push ( * i) ;
1567- }
1568- while let Some ( i) = queue. pop ( ) {
1569- if let Some ( deps) = self . edges . get ( & i) {
1570- for j in deps {
1571- if self . edges . contains_key ( j) && reachable. insert ( * j) {
1572- queue. push ( * j) ;
1573- }
1564+ fn get_reachable ( mut self ) -> Vec < UnitSectionOffset > {
1565+ let mut reachable = Vec :: new ( ) ;
1566+ let mut queue = vec ! [ self . required] ;
1567+ while let Some ( entries) = queue. pop ( ) {
1568+ for entry in entries {
1569+ if let Some ( deps) = self . edges . remove ( & entry) {
1570+ reachable. push ( entry) ;
1571+ queue. push ( deps) ;
15741572 }
15751573 }
15761574 }
1577- let mut offsets: Vec < _ > = reachable. into_iter ( ) . collect ( ) ;
1578- offsets. sort_unstable ( ) ;
1579- offsets
1575+ reachable. sort_unstable ( ) ;
1576+ reachable
15801577 }
15811578 }
15821579
@@ -1776,8 +1773,6 @@ pub(crate) mod convert {
17761773 }
17771774
17781775 let entry_offset = offset. to_unit_section_offset ( & self . unit ) ;
1779- self . deps . add_entry ( entry_offset) ;
1780-
17811776 let mut entry = FilterUnitEntry {
17821777 unit : self . unit ,
17831778 offset,
@@ -1788,16 +1783,18 @@ pub(crate) mod convert {
17881783 parent_tag : parent. map ( |p| p. tag ) ,
17891784 } ;
17901785 Self :: read_attributes ( & mut entry, & mut self . entries , abbrev. attributes ( ) ) ?;
1786+ let mut deps = Vec :: new ( ) ;
17911787 for attr in & entry. attrs {
1792- self . add_attribute_refs ( entry_offset , attr. value ( ) ) ?;
1788+ self . add_attribute_refs ( & mut deps , attr. value ( ) ) ?;
17931789 }
17941790 if let Some ( parent) = parent {
17951791 let parent_offset = parent. offset . to_unit_section_offset ( & self . unit ) ;
1796- self . deps . add_edge ( entry_offset , parent_offset) ;
1792+ deps. push ( parent_offset) ;
17971793 if parent. tag != constants:: DW_TAG_namespace && entry. has_die_back_edge ( ) {
17981794 self . deps . add_edge ( parent_offset, entry_offset) ;
17991795 }
18001796 }
1797+ self . deps . add_entry ( entry_offset, deps) ;
18011798
18021799 return Ok ( Some ( entry) ) ;
18031800 }
@@ -1831,31 +1828,30 @@ pub(crate) mod convert {
18311828
18321829 fn add_attribute_refs (
18331830 & mut self ,
1834- entry_offset : UnitSectionOffset ,
1831+ deps : & mut Vec < UnitSectionOffset > ,
18351832 value : read:: AttributeValue < R > ,
18361833 ) -> ConvertResult < ( ) > {
18371834 match value {
18381835 read:: AttributeValue :: UnitRef ( val) => {
18391836 // This checks that the offset is within bounds, but not that it refers to a valid DIE.
18401837 if val. is_in_bounds ( & self . unit ) {
1841- self . deps
1842- . add_edge ( entry_offset, val. to_unit_section_offset ( & self . unit ) ) ;
1838+ deps. push ( val. to_unit_section_offset ( & self . unit ) ) ;
18431839 }
18441840 }
18451841 read:: AttributeValue :: DebugInfoRef ( val) => {
18461842 let offset = val
18471843 . to_unit_section_offset ( & self . unit )
18481844 . ok_or ( ConvertError :: InvalidDebugInfoRef ) ?;
1849- self . deps . add_edge ( entry_offset , offset) ;
1845+ deps. push ( offset) ;
18501846 }
18511847 read:: AttributeValue :: Exprloc ( expression) => {
1852- self . add_expression_refs ( entry_offset , expression. clone ( ) ) ?;
1848+ self . add_expression_refs ( deps , expression. clone ( ) ) ?;
18531849 }
18541850 read:: AttributeValue :: LocationListsRef ( val) => {
1855- self . add_location_refs ( entry_offset , val) ?;
1851+ self . add_location_refs ( deps , val) ?;
18561852 }
18571853 read:: AttributeValue :: DebugLocListsIndex ( index) => {
1858- self . add_location_refs ( entry_offset , self . unit . locations_offset ( index) ?) ?;
1854+ self . add_location_refs ( deps , self . unit . locations_offset ( index) ?) ?;
18591855 }
18601856 _ => ( ) ,
18611857 }
@@ -1864,19 +1860,19 @@ pub(crate) mod convert {
18641860
18651861 fn add_location_refs (
18661862 & mut self ,
1867- entry_offset : UnitSectionOffset ,
1863+ deps : & mut Vec < UnitSectionOffset > ,
18681864 offset : LocationListsOffset ,
18691865 ) -> ConvertResult < ( ) > {
18701866 let mut locations = self . unit . locations ( offset) ?;
18711867 while let Some ( location) = locations. next ( ) ? {
1872- self . add_expression_refs ( entry_offset , location. data ) ?;
1868+ self . add_expression_refs ( deps , location. data ) ?;
18731869 }
18741870 Ok ( ( ) )
18751871 }
18761872
18771873 fn add_expression_refs (
18781874 & mut self ,
1879- entry_offset : UnitSectionOffset ,
1875+ deps : & mut Vec < UnitSectionOffset > ,
18801876 expression : read:: Expression < R > ,
18811877 ) -> ConvertResult < ( ) > {
18821878 let mut ops = expression. operations ( self . unit . encoding ( ) ) ;
@@ -1904,8 +1900,7 @@ pub(crate) mod convert {
19041900 ..
19051901 } => {
19061902 if offset. is_in_bounds ( & self . unit ) {
1907- self . deps
1908- . add_edge ( entry_offset, offset. to_unit_section_offset ( & self . unit ) ) ;
1903+ deps. push ( offset. to_unit_section_offset ( & self . unit ) ) ;
19091904 }
19101905 }
19111906 read:: Operation :: Call {
@@ -1915,7 +1910,7 @@ pub(crate) mod convert {
19151910 let offset = ref_offset
19161911 . to_unit_section_offset ( & self . unit )
19171912 . ok_or ( ConvertError :: InvalidDebugInfoRef ) ?;
1918- self . deps . add_edge ( entry_offset , offset) ;
1913+ deps. push ( offset) ;
19191914 }
19201915 _ => { }
19211916 }
0 commit comments