diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 46b8a7be..61448c68 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -1928,7 +1928,7 @@ impl TopLevelComposer { &args, &fun_body, 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( diff --git a/nac3core/src/typecheck/escape_analysis/lifetime.rs b/nac3core/src/typecheck/escape_analysis/lifetime.rs index ff4ee047..942527e6 100644 --- a/nac3core/src/typecheck/escape_analysis/lifetime.rs +++ b/nac3core/src/typecheck/escape_analysis/lifetime.rs @@ -123,7 +123,7 @@ impl LifetimeIRBuilder { LifetimeIR::Branch { targets } => { destination_mapping.insert(i, targets); } - _ => unreachable!(), + _ => () } } } @@ -155,28 +155,30 @@ impl LifetimeIRBuilder { pub fn analyze(&self) -> Result<(), String> { let mut analyzers = HashMap::new(); - analyzers.insert(0, LifetimeAnalyzer::new()); + analyzers.insert(0, (0, true, LifetimeAnalyzer::new())); let mut worklist = vec![0]; - let mut counter = 0; while let Some(bb) = worklist.pop() { - counter += 1; - if counter > 100 { - return Err(format!("escape analyzer stuck in infinite loop?")); + let (counter, updated, analyzer) = analyzers.get_mut(&bb).unwrap(); + *counter += 1; + 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 ir_iter = block.iter().filter_map(|&id| { self.irs[id].as_ref().map(|(ir, loc)| (LifetimeId(id), ir, *loc)) }); if let Some(branch) = analyzer.analyze_basic_block(ir_iter)? { for &target in branch.iter() { - if let Some(successor) = analyzers.get_mut(&target.0) { - if successor.merge(&analyzer) { + if let Some((_, updated, successor)) = analyzers.get_mut(&target.0) { + if successor.merge(&analyzer) && !*updated { // changed worklist.push(target.0); + *updated = true; } } else { - analyzers.insert(target.0, analyzer.clone()); + analyzers.insert(target.0, (0, true, analyzer.clone())); worklist.push(target.0); } } diff --git a/nac3core/src/typecheck/escape_analysis/mod.rs b/nac3core/src/typecheck/escape_analysis/mod.rs index 971cd119..9bd255f6 100644 --- a/nac3core/src/typecheck/escape_analysis/mod.rs +++ b/nac3core/src/typecheck/escape_analysis/mod.rs @@ -67,7 +67,10 @@ impl<'a> EscapeAnalyzer<'a> { } } 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 { diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index 37925157..a87b9494 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -220,7 +220,11 @@ fn main() { let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache); 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());