introduce an early pass to clear dead blocks
this makes the the MIR assignment pass complete successfully
This commit is contained in:
parent
999f1767ca
commit
67d1cf1122
@ -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 {
|
||||
|
62
src/librustc_mir/transform/clear_dead_blocks.rs
Normal file
62
src/librustc_mir/transform/clear_dead_blocks.rs
Normal 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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user