1
0
forked from M-Labs/nac3

escape analysis: fixed infinite loop detection

This commit is contained in:
pca006132 2022-04-08 09:18:34 +08:00
parent 1257a80ed1
commit fb79b47b38
4 changed files with 22 additions and 13 deletions
nac3core/src
toplevel
typecheck/escape_analysis
nac3standalone/src

View File

@ -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(

View File

@ -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);
} }
} }

View File

@ -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 {

View File

@ -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());