Skip to content

Commit ec3c8fd

Browse files
authored
Merge pull request #133 from intel/disable-register-size-check
Fixes related to paramater resolution
2 parents 02d2a9d + e656829 commit ec3c8fd

File tree

7 files changed

+186
-123
lines changed

7 files changed

+186
-123
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
correctly parsed.
1212
- You can now annotate dml source to disable reporting of specific lints for specific files or lines,
1313
see [USAGE.md](USAGE.md) for instructions on how to use it
14+
- Disabled the invariant check for the parameter 'size' to be set on register
15+
objects. Will be re-enabled when constant-folding is added to the DLS.
16+
- Fixed issue where statements under top-level in-eachs were not correctly tracked.
17+
- Moved storage of reference->symbol mapping to on-demand timing, should significantly speed
18+
up device analysises
1419

1520
## 0.9.12
1621
- Added 'simics\_util\_vect' as a known provisional (with no DLS semantics)

src/actions/requests.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
88
use serde_json::Value;
99
use std::collections::HashSet;
1010
use std::path::Path;
11-
use std::sync::Arc;
1211

1312
use crate::actions::hover;
1413
use crate::actions::{AnalysisProgressKind, AnalysisWaitKind,
@@ -192,7 +191,6 @@ fn fp_to_symbol_refs<O: Output>
192191
for device in analysis.filtered_device_analysises_containing_file(
193192
&canon_path,
194193
filter.as_ref()) {
195-
debug!("reference info is {:?}", device.reference_info.keys());
196194
// NOTE: This ends up being the correct place to warn users
197195
// about references inside uninstantiated templates,
198196
// but we have to perform some extra work to find out we are
@@ -206,12 +204,9 @@ fn fp_to_symbol_refs<O: Output>
206204
any_template_used = true;
207205
}
208206
}
209-
if let Some(defs) = device.reference_info.get(
210-
refr.loc_span()) {
211-
for def in defs {
212-
definitions.push(Arc::clone(def));
213-
}
214-
}
207+
208+
definitions.append(
209+
&mut device.symbols_of_ref(*refr.loc_span()));
215210
}
216211
if let Some(ContextKey::Template(_)) = first_context {
217212
if !any_template_used {

src/analysis/mod.rs

Lines changed: 150 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
20312042
impl 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

22282303
pub fn from_device_and_bases<'a>(_device: &'a IsolatedAnalysis,

src/analysis/structure/toplevel.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,20 @@ impl TopLevel {
659659
|stmnt|ObjectDecl::always(stmnt)).collect();
660660
let mut errors = statements.errors.iter().map(
661661
|stmnt|ObjectDecl::always(stmnt)).collect();
662-
let mut ineachs = statements.ineachs.iter().map(
663-
|stmnt|ObjectDecl::always(stmnt)).collect();
662+
let mut ineachs = vec![];
663+
664+
for ineach in &statements.ineachs {
665+
let spec = flatten_hashif_branch(StatementContext::Object,
666+
&ineach.statements,
667+
vec![], report);
668+
ineachs.push(
669+
ObjectDecl {
670+
cond: ExistCondition::Always,
671+
obj: ineach.clone(),
672+
spec,
673+
});
674+
}
675+
664676
let mut templates = vec![];
665677
let mut loggroups = vec![];
666678
let mut constants = vec![];

0 commit comments

Comments
 (0)