From 67d1cf112218257025edf75b9cb7ebc8ab8bfa64 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 7 Feb 2016 23:09:15 +0200 Subject: [PATCH] introduce an early pass to clear dead blocks this makes the the MIR assignment pass complete successfully --- src/librustc_mir/mir_map.rs | 4 +- .../transform/clear_dead_blocks.rs | 62 +++++++++++++++++++ src/librustc_mir/transform/mod.rs | 1 + src/librustc_mir/transform/type_check.rs | 8 --- 4 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 src/librustc_mir/transform/clear_dead_blocks.rs diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 58b6d69ba5c1..68d85dc8394b 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -22,7 +22,8 @@ extern crate rustc_front; use build; use graphviz; use pretty; -use transform::{simplify_cfg, type_check, no_landing_pads}; +use transform::{clear_dead_blocks, simplify_cfg, type_check}; +use transform::{no_landing_pads}; use rustc::dep_graph::DepNode; use rustc::mir::repr::Mir; use hair::cx::Cx; @@ -148,6 +149,7 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> { match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) { Ok(mut mir) => { + clear_dead_blocks::ClearDeadBlocks::new().run_on_mir(&mut mir, self.tcx); type_check::TypeckMir::new(&infcx).run_on_mir(&mut mir, self.tcx); no_landing_pads::NoLandingPads.run_on_mir(&mut mir, self.tcx); if self.tcx.sess.opts.mir_opt_level > 0 { diff --git a/src/librustc_mir/transform/clear_dead_blocks.rs b/src/librustc_mir/transform/clear_dead_blocks.rs new file mode 100644 index 000000000000..88c0116f26d2 --- /dev/null +++ b/src/librustc_mir/transform/clear_dead_blocks.rs @@ -0,0 +1,62 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A pass that erases the contents of dead blocks. This is required +//! because rustc allows for ill-typed block terminators in dead +//! blocks. +//! +//! This pass does not renumber or remove the blocks, to have the +//! MIR better match the source. + +use rustc::middle::ty; +use rustc::mir::repr::*; +use rustc::mir::transform::MirPass; + +pub struct ClearDeadBlocks; + +impl ClearDeadBlocks { + pub fn new() -> ClearDeadBlocks { + ClearDeadBlocks + } + + fn clear_dead_blocks(&self, mir: &mut Mir) { + let mut seen = vec![false; mir.basic_blocks.len()]; + + // These blocks are always required. + seen[START_BLOCK.index()] = true; + seen[END_BLOCK.index()] = true; + + let mut worklist = vec![START_BLOCK]; + while let Some(bb) = worklist.pop() { + for succ in mir.basic_block_data(bb).terminator().successors().iter() { + if !seen[succ.index()] { + seen[succ.index()] = true; + worklist.push(*succ); + } + } + } + + for (block, seen) in mir.basic_blocks.iter_mut().zip(seen) { + if !seen { + *block = BasicBlockData { + statements: vec![], + terminator: Some(Terminator::Return), + is_cleanup: false + }; + } + } + } +} + +impl MirPass for ClearDeadBlocks { + fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, _tcx: &ty::ctxt<'tcx>) { + self.clear_dead_blocks(mir); + } +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 64e188a3b558..d27c208041fa 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +pub mod clear_dead_blocks; pub mod simplify_cfg; pub mod erase_regions; pub mod no_landing_pads; diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 3a891543e801..f4d83cd05e08 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -125,14 +125,6 @@ impl<'a, 'tcx> TypeckMir<'a, 'tcx> { let tcx = self.tcx(); match stmt.kind { StatementKind::Assign(ref lv, ref rv) => { - match lv { - &Lvalue::ReturnPointer if mir.return_ty == ty::FnDiverging => { - // HACK: buggy writes - return; - } - _ => {} - } - let lv_ty = mir.lvalue_ty(tcx, lv).to_ty(tcx); let rv_ty = mir.rvalue_ty(tcx, rv); if let Some(rv_ty) = rv_ty {