forked from M-Labs/nac3
escape analysis: fixed infinite loop detection
This commit is contained in:
parent
1257a80ed1
commit
fb79b47b38
|
@ -1928,7 +1928,7 @@ impl TopLevelComposer {
|
||||||
&args,
|
&args,
|
||||||
&fun_body,
|
&fun_body,
|
||||||
ast.as_ref().unwrap().location,
|
ast.as_ref().unwrap().location,
|
||||||
).map_err(|e| format!("Escape analysis error: {}\n in function {}", e, name))?;
|
).map_err(|e| format!("Escape analysis error: {}\n ... in function {}", e, name))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance_to_stmt.insert(
|
instance_to_stmt.insert(
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl LifetimeIRBuilder {
|
||||||
LifetimeIR::Branch { targets } => {
|
LifetimeIR::Branch { targets } => {
|
||||||
destination_mapping.insert(i, targets);
|
destination_mapping.insert(i, targets);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,28 +155,30 @@ impl LifetimeIRBuilder {
|
||||||
|
|
||||||
pub fn analyze(&self) -> Result<(), String> {
|
pub fn analyze(&self) -> Result<(), String> {
|
||||||
let mut analyzers = HashMap::new();
|
let mut analyzers = HashMap::new();
|
||||||
analyzers.insert(0, LifetimeAnalyzer::new());
|
analyzers.insert(0, (0, true, LifetimeAnalyzer::new()));
|
||||||
let mut worklist = vec![0];
|
let mut worklist = vec![0];
|
||||||
let mut counter = 0;
|
|
||||||
while let Some(bb) = worklist.pop() {
|
while let Some(bb) = worklist.pop() {
|
||||||
counter += 1;
|
let (counter, updated, analyzer) = analyzers.get_mut(&bb).unwrap();
|
||||||
if counter > 100 {
|
*counter += 1;
|
||||||
return Err(format!("escape analyzer stuck in infinite loop?"));
|
if *counter > 100 {
|
||||||
|
return Err(format!("infinite loop detected at basic block {}", bb));
|
||||||
}
|
}
|
||||||
let mut analyzer = analyzers.get(&bb).unwrap().clone();
|
*updated = false;
|
||||||
|
let mut analyzer = analyzer.clone();
|
||||||
let block = &self.basic_blocks[bb];
|
let block = &self.basic_blocks[bb];
|
||||||
let ir_iter = block.iter().filter_map(|&id| {
|
let ir_iter = block.iter().filter_map(|&id| {
|
||||||
self.irs[id].as_ref().map(|(ir, loc)| (LifetimeId(id), ir, *loc))
|
self.irs[id].as_ref().map(|(ir, loc)| (LifetimeId(id), ir, *loc))
|
||||||
});
|
});
|
||||||
if let Some(branch) = analyzer.analyze_basic_block(ir_iter)? {
|
if let Some(branch) = analyzer.analyze_basic_block(ir_iter)? {
|
||||||
for &target in branch.iter() {
|
for &target in branch.iter() {
|
||||||
if let Some(successor) = analyzers.get_mut(&target.0) {
|
if let Some((_, updated, successor)) = analyzers.get_mut(&target.0) {
|
||||||
if successor.merge(&analyzer) {
|
if successor.merge(&analyzer) && !*updated {
|
||||||
// changed
|
// changed
|
||||||
worklist.push(target.0);
|
worklist.push(target.0);
|
||||||
|
*updated = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
analyzers.insert(target.0, analyzer.clone());
|
analyzers.insert(target.0, (0, true, analyzer.clone()));
|
||||||
worklist.push(target.0);
|
worklist.push(target.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,10 @@ impl<'a> EscapeAnalyzer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zelf.handle_statements(body)?;
|
zelf.handle_statements(body)?;
|
||||||
zelf.builder.analyze()
|
zelf.builder.remove_empty_bb();
|
||||||
|
zelf.builder.analyze().map_err(|e| {
|
||||||
|
format!("{}\nIR: {}", e, zelf.builder.print_ir())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn need_alloca(&mut self, ty: Type) -> bool {
|
fn need_alloca(&mut self, ty: Type) -> bool {
|
||||||
|
|
|
@ -220,7 +220,11 @@ fn main() {
|
||||||
let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache);
|
let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache);
|
||||||
let signature = store.add_cty(signature);
|
let signature = store.add_cty(signature);
|
||||||
|
|
||||||
composer.start_analysis(true).unwrap();
|
if let Err(e) = composer.start_analysis(true) {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let top_level = Arc::new(composer.make_top_level_context());
|
let top_level = Arc::new(composer.make_top_level_context());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue