@@ -376,9 +376,19 @@ pub struct SymbolStorage {
376376 pub variable_symbols : HashMap < ZeroSpan , SymbolRef > ,
377377}
378378
379- // This maps non-auth symbol decls to auth decl
380- // and references to the symbol decl they ref
381- type ReferenceStorage = HashMap < ZeroSpan , Vec < SymbolRef > > ;
379+ impl SymbolStorage {
380+ pub fn all_symbols < ' a > ( & ' a self ) -> impl Iterator < Item = & ' a SymbolRef > {
381+ self . template_symbols . values ( )
382+ . chain ( self . param_symbols . values ( ) . flat_map ( |h|h. values ( ) ) )
383+ . chain ( self . object_symbols . values ( ) )
384+ . chain ( self . method_symbols . values ( ) )
385+ . chain ( self . variable_symbols . values ( ) )
386+ }
387+ }
388+
389+ // This maps references to the symbol they reference, made as a lock
390+ // because we need to incrementally fill it as requests are made
391+ type ReferenceStorage = Arc < Mutex < HashMap < ZeroSpan , Vec < SymbolRef > > > > ;
382392
383393// Analysis from the perspective of a particular DML device
384394#[ derive( Debug , Clone ) ]
@@ -1356,7 +1366,7 @@ impl DeviceAnalysis {
13561366 ReferenceMatch :: Found ( symbols) =>
13571367 for symbol in & symbols {
13581368 let mut sym = symbol. lock ( ) . unwrap ( ) ;
1359- sym. references . push ( * reference. loc_span ( ) ) ;
1369+ sym. references . insert ( * reference. loc_span ( ) ) ;
13601370 if let Some ( meth) = sym. source
13611371 . as_object ( )
13621372 . and_then ( DMLObject :: as_shallow)
@@ -1622,7 +1632,7 @@ fn template_to_symbol(template: &Arc<DMLTemplate>) -> Option<SymbolRef> {
16221632 Arc :: new ( Mutex :: new ( Symbol {
16231633 loc : * location,
16241634 kind : DMLSymbolKind :: Template ,
1625- references : vec ! [ ] ,
1635+ references : HashSet :: default ( ) ,
16261636 definitions : vec ! [ * location] ,
16271637 declarations : vec ! [ * location] ,
16281638 implementations : vec ! [ ] ,
@@ -1659,7 +1669,7 @@ fn new_symbol_from_object(object: &DMLCompositeObject) -> SymbolRef {
16591669 definitions : all_decl_defs. clone ( ) ,
16601670 declarations : all_decl_defs. clone ( ) ,
16611671 bases : all_decl_defs,
1662- references : vec ! [ ] ,
1672+ references : HashSet :: default ( ) ,
16631673 implementations : vec ! [ ] ,
16641674 source : SymbolSource :: DMLObject (
16651675 DMLObject :: CompObject ( object. key ) ) ,
@@ -1679,7 +1689,7 @@ fn new_symbol_from_arg(methref: &Arc<DMLMethodRef>,
16791689 bases,
16801690 definitions,
16811691 declarations,
1682- references : vec ! [ ] ,
1692+ references : HashSet :: default ( ) ,
16831693 implementations : vec ! [ ] ,
16841694 source : SymbolSource :: MethodArg ( Arc :: clone ( methref) ,
16851695 arg. name ( ) . clone ( ) ) ,
@@ -1752,7 +1762,7 @@ fn add_new_symbol_from_shallow(shallow: &DMLShallowObject,
17521762 definitions,
17531763 declarations,
17541764 implementations : vec ! [ ] ,
1755- references : vec ! [ ] ,
1765+ references : HashSet :: default ( ) ,
17561766 bases,
17571767 source : SymbolSource :: DMLObject (
17581768 // TODO: Inefficient clone. Not terribly so, but worth
@@ -1834,7 +1844,7 @@ where
18341844 definitions : vec ! [ * sym. loc_span( ) ] ,
18351845 declarations : vec ! [ * sym. loc_span( ) ] ,
18361846 implementations : vec ! [ ] ,
1837- references : vec ! [ ] ,
1847+ references : HashSet :: default ( ) ,
18381848 bases : vec ! [ ] ,
18391849 source : SymbolSource :: MethodLocal (
18401850 Arc :: clone ( method) ,
@@ -2028,7 +2038,68 @@ fn add_new_method_scope_symbols(method: &Arc<DMLMethodRef>,
20282038 }
20292039}
20302040
2041+
20312042impl DeviceAnalysis {
2043+ fn make_templates_traits ( start_of_file : & ZeroSpan ,
2044+ rank_maker : & mut RankMaker ,
2045+ unique_templates : & HashMap <
2046+ & str , & ObjectDecl < Template > > ,
2047+ files : & HashMap < & str , & TopLevel > ,
2048+ imp_map : & HashMap < Import , String > ,
2049+ errors : & mut Vec < DMLError > )
2050+ -> TemplateTraitInfo {
2051+ info ! ( "Rank templates" ) ;
2052+ let ( templates, order, invalid_isimps, rank_struct)
2053+ = rank_templates ( unique_templates, files, imp_map, errors) ;
2054+ info ! ( "Templates+traits" ) ;
2055+ create_templates_traits (
2056+ start_of_file,
2057+ rank_maker, templates, order,
2058+ invalid_isimps, imp_map, rank_struct, errors)
2059+ }
2060+
2061+ fn match_references ( & mut self ,
2062+ bases : & Vec < IsolatedAnalysis > ,
2063+ method_structure : & HashMap < ZeroSpan , RangeEntry > ,
2064+ errors : & mut Vec < DMLError > ) {
2065+ info ! ( "Match references" ) ;
2066+ let reference_cache: Mutex < ReferenceCache > = Mutex :: default ( ) ;
2067+ for scope_chain in all_scopes ( bases) {
2068+ self . match_references_in_scope ( scope_chain,
2069+ errors,
2070+ method_structure,
2071+ & reference_cache) ;
2072+ }
2073+ }
2074+
2075+ fn template_object_map ( tt_info : & TemplateTraitInfo ,
2076+ container : & StructureContainer )
2077+ -> HashMap < ZeroSpan , Vec < StructureKey > > {
2078+ // Tie objects to their implemented templates, and vice-versa
2079+ // NOTE: This cannot be inside DMLTemplates, because due to RC
2080+ // references they are immutable once created
2081+ trace ! ( "template->object map" ) ;
2082+ // maps template declaration loc to objects
2083+ let mut template_object_implementation_map: HashMap < ZeroSpan ,
2084+ Vec < StructureKey > >
2085+ = HashMap :: new ( ) ;
2086+ for template in tt_info. templates . values ( ) {
2087+ if let Some ( loc) = template. location . as_ref ( ) {
2088+ template_object_implementation_map. insert ( * loc, vec ! [ ] ) ;
2089+ }
2090+ }
2091+ for object in container. values ( ) {
2092+ for template in object. templates . values ( ) {
2093+ if let Some ( loc) = template. location . as_ref ( ) {
2094+ template_object_implementation_map
2095+ . entry ( * loc)
2096+ . or_default ( ) . push ( object. key ) ;
2097+ }
2098+ }
2099+ }
2100+ template_object_implementation_map
2101+ }
2102+
20322103 pub fn new ( root : IsolatedAnalysis ,
20332104 timed_bases : Vec < TimestampedStorage < IsolatedAnalysis > > ,
20342105 imp_map : HashMap < Import , String > )
@@ -2105,15 +2176,13 @@ impl DeviceAnalysis {
21052176 trace ! ( "Tracked file {} as template" ,
21062177 base. path. to_str( ) . unwrap_or( "no path" ) ) ;
21072178 }
2108- info ! ( "Rank templates" ) ;
2109- let ( templates, order, invalid_isimps, rank_struct)
2110- = rank_templates ( & unique_templates, & files, & imp_map, & mut errors) ;
2111- let mut rankmaker = RankMaker :: new ( ) ;
2112- info ! ( "Templates+traits" ) ;
2113- let tt_info = create_templates_traits (
2114- & root. toplevel . start_of_file ,
2115- & mut rankmaker, templates, order,
2116- invalid_isimps, & imp_map, rank_struct, & mut errors) ;
2179+ let mut rank_maker = RankMaker :: new ( ) ;
2180+ let tt_info = Self :: make_templates_traits ( & root. toplevel . start_of_file ,
2181+ & mut rank_maker,
2182+ & unique_templates,
2183+ & files,
2184+ & imp_map,
2185+ & mut errors) ;
21172186
21182187 // TODO: catch typedef/traitname overlaps
21192188
@@ -2122,37 +2191,19 @@ impl DeviceAnalysis {
21222191 info ! ( "Make device" ) ;
21232192 let device_key = make_device ( root. path . as_str ( ) , & root. toplevel ,
21242193 & tt_info, imp_map, & mut container,
2125- & mut rankmaker, & mut errors) . key ;
2126- // Tie objects to their implemented templates, and vice-versa
2127- // NOTE: This cannot be inside DMLTemplates, because due to RC
2128- // references they are immutable once created
2129- trace ! ( "template->object map" ) ;
2194+ & mut rank_maker, & mut errors) . key ;
2195+
21302196 // maps template declaration loc to objects
2131- let mut template_object_implementation_map: HashMap < ZeroSpan ,
2132- Vec < StructureKey > >
2133- = HashMap :: new ( ) ;
2134- for template in tt_info. templates . values ( ) {
2135- if let Some ( loc) = template. location . as_ref ( ) {
2136- template_object_implementation_map. insert ( * loc, vec ! [ ] ) ;
2137- }
2138- }
2139- for object in container. values ( ) {
2140- for template in object. templates . values ( ) {
2141- if let Some ( loc) = template. location . as_ref ( ) {
2142- template_object_implementation_map
2143- . entry ( * loc)
2144- . or_default ( ) . push ( object. key ) ;
2145- }
2146- }
2147- }
2197+ let template_object_implementation_map =
2198+ Self :: template_object_map ( & tt_info, & container) ;
21482199
21492200 info ! ( "Generate symbols" ) ;
21502201 // Used to handle scoping in methods when looking up local symbols,
21512202 // NOTE: if this meta-information becomes relevant later, move this
21522203 // structure to symbol storage
21532204 // The zerospan here is the span corresponding to the span of the
21542205 // NAME of the methoddecl
2155- let mut method_structure: HashMap < ZeroSpan , RangeEntry >
2206+ let mut method_structure: HashMap < ZeroSpan , RangeEntry >
21562207 = HashMap :: default ( ) ;
21572208
21582209 let mut symbol_info = objects_to_symbols ( & container,
@@ -2169,48 +2220,22 @@ impl DeviceAnalysis {
21692220 device_obj : DMLObject :: CompObject ( device_key) ,
21702221 templates : tt_info,
21712222 symbol_info,
2172- reference_info : ReferenceStorage :: new ( ) ,
2223+ reference_info : ReferenceStorage :: default ( ) ,
21732224 template_object_implementation_map,
21742225 path : root. path . clone ( ) ,
21752226 clientpath : root. path . clone ( ) . into ( ) ,
21762227 dependant_files : bases. iter ( ) . map ( |b|& b. path ) . cloned ( ) . collect ( ) ,
21772228 } ;
21782229
2179- info ! ( "Match references" ) ;
2180- let reference_cache: Mutex < ReferenceCache > = Mutex :: default ( ) ;
2181- for scope_chain in all_scopes ( & bases) {
2182- device. match_references_in_scope ( scope_chain,
2183- & mut errors,
2184- & method_structure,
2185- & reference_cache) ;
2186- }
2230+ device. match_references ( & bases, & method_structure, & mut errors) ;
21872231
2188- info ! ( "Inverse map" ) ;
2189- // Set up the inverse map of references->symbols
2190- for symbol in device. symbol_info . template_symbols . values ( )
2191- . chain ( device. symbol_info . param_symbols
2192- . values ( ) . flat_map ( |h|h. values ( ) ) )
2193- . chain ( device. symbol_info . object_symbols . values ( ) )
2194- . chain ( device. symbol_info . method_symbols . values ( ) )
2195- . chain ( device. symbol_info . variable_symbols . values ( ) ) {
2196- debug ! ( "Inverse of {:?}" , symbol) ;
2197- for ref_loc in & symbol. lock ( ) . unwrap ( ) . references {
2198- device. reference_info . entry ( * ref_loc)
2199- . or_default ( ) . push ( Arc :: clone ( symbol) ) ;
2200- }
2201- }
2232+ // NOTE: This is when we previously pre-calculated the ref->symbol map, however
2233+ // the up-front analysis cost of this was too heavy
2234+ // device.inverse_references();
22022235
2203- info ! ( "Implementation map" ) ;
2204- for ( templ_loc, objects) in & device. template_object_implementation_map {
2205- if let Some ( templ) = device. symbol_info
2206- . template_symbols . get ( templ_loc) {
2207- let mut sym_mut = templ. lock ( ) . unwrap ( ) ;
2208- sym_mut. implementations . extend (
2209- objects. iter ( ) . flat_map (
2210- |obj|device. objects . get ( * obj) . unwrap ( )
2211- . all_decls . iter ( ) . map (
2212- |spec|* spec. loc_span ( ) ) ) ) ;
2213- }
2236+ info ! ( "Invariant check" ) ;
2237+ for obj in device. objects . values ( ) {
2238+ device. param_invariants ( obj, & mut errors) ;
22142239 }
22152240
22162241 for error in errors {
@@ -2223,6 +2248,56 @@ impl DeviceAnalysis {
22232248 info ! ( "Done with device" ) ;
22242249 Ok ( device)
22252250 }
2251+
2252+ #[ allow( clippy:: ptr_arg) ]
2253+ fn param_invariants ( & self ,
2254+ obj : & DMLCompositeObject ,
2255+ _report : & mut Vec < DMLError > ) {
2256+ #[ allow( clippy:: single_match) ]
2257+ match & obj. kind {
2258+ // TODO: Check 'name' parameter towards 'ident' parameter
2259+ CompObjectKind :: Register => {
2260+ // TODO: Cannot be sufficiently checked until
2261+ // constant-folding is in
2262+ // NOTE: 'offset' is checked by the requirement of
2263+ // the register template. Might be better to give
2264+ // a nicer error here
2265+ // match self.lookup_def_in_comp_object(
2266+ // obj, "size", None) {
2267+ // // TODO: verify size is an integer
2268+ // ReferenceMatch::Found(_) => (),
2269+ // _ => {
2270+ // report.push(DMLError {
2271+ // span: obj.declloc,
2272+ // description: "No assignment to 'size' parameter \
2273+ // in register".to_string(),
2274+ // related: vec![],
2275+ // severity: Some(DiagnosticSeverity::ERROR),
2276+ // });
2277+ // },
2278+ // }
2279+ } ,
2280+ _ => ( ) ,
2281+ }
2282+ }
2283+
2284+ pub fn symbols_of_ref ( & self , loc : ZeroSpan ) -> Vec < SymbolRef > {
2285+ // Would like to use .entry here, but it does not play nice with the
2286+ // mutable borrow of .reference_info and .symbol_info
2287+ let mut locked_info = self . reference_info . lock ( ) . unwrap ( ) ;
2288+ if let Some ( syms) = locked_info. get ( & loc) {
2289+ syms. clone ( )
2290+ } else {
2291+ let mut syms = vec ! [ ] ;
2292+ for sym in self . symbol_info . all_symbols ( ) {
2293+ if sym. lock ( ) . unwrap ( ) . references . contains ( & loc) {
2294+ syms. push ( Arc :: clone ( sym) ) ;
2295+ }
2296+ }
2297+ locked_info. insert ( loc, syms) ;
2298+ locked_info. get ( & loc) . unwrap ( ) . clone ( )
2299+ }
2300+ }
22262301}
22272302
22282303pub fn from_device_and_bases < ' a > ( _device : & ' a IsolatedAnalysis ,
0 commit comments