introduce an early pass to clear dead blocks

this makes the the MIR assignment pass complete successfully
This commit is contained in:
Ariel Ben-Yehuda 2016-02-07 23:09:15 +02:00 committed by Ariel Ben-Yehuda
parent 999f1767ca
commit 67d1cf1122
4 changed files with 66 additions and 9 deletions

View file

@ -22,7 +22,8 @@
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 @@ fn visit_fn(&mut self,
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 {

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
}
}

View file

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

View file

@ -125,14 +125,6 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'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 {