From f976e222e97fdcb8ab66634c8910ce524f6804c9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 22 Mar 2016 16:19:44 -0400 Subject: [PATCH] fix bug in `simplify_cfg` with inf. loops --- src/librustc_mir/transform/simplify_cfg.rs | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index d1f9a5bd259..21b1d022fda 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -12,6 +12,7 @@ use rustc::middle::ty::TyCtxt; use rustc::mir::repr::*; use rustc::mir::transform::{MirPass, Pass}; +use pretty; use syntax::ast::NodeId; use super::remove_dead_blocks::RemoveDeadBlocks; @@ -30,16 +31,22 @@ fn final_target(mir: &Mir, mut target: BasicBlock) -> Option { let mut seen: Vec = Vec::with_capacity(8); while mir.basic_block_data(target).statements.is_empty() { - debug!("final_target: target={:?}", target); - match mir.basic_block_data(target).terminator().kind { - TerminatorKind::Goto { target: next } => { - if seen.contains(&next) { - return None; + // NB -- terminator may have been swapped with `None` + // below, in which case we have a cycle and just want + // to stop + if let Some(ref terminator) = mir.basic_block_data(target).terminator { + match terminator.kind { + TerminatorKind::Goto { target: next } => { + if seen.contains(&next) { + return None; + } + seen.push(next); + target = next; } - seen.push(next); - target = next; + _ => break } - _ => break + } else { + break } } @@ -106,8 +113,11 @@ fn simplify_branches(&self, mir: &mut Mir) -> bool { impl<'tcx> MirPass<'tcx> for SimplifyCfg { fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, id: NodeId, mir: &mut Mir<'tcx>) { + let mut counter = 0; let mut changed = true; while changed { + pretty::dump_mir(tcx, "simplify_cfg", &counter, id, mir, None); + counter += 1; changed = self.simplify_branches(mir); changed |= self.remove_goto_chains(mir); RemoveDeadBlocks.run_pass(tcx, id, mir); -- 2.44.0