about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <arielb1@mail.tau.ac.il>2016-02-07 23:09:15 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2016-02-20 01:45:13 +0200
commit67d1cf112218257025edf75b9cb7ebc8ab8bfa64 (patch)
tree4cdaa2a2ed85462b8664d8b6dfa5e7690b59a7bc /src
parent999f1767caeb62a60278ae5afd9191dfbbd6ef18 (diff)
downloadrust-67d1cf112218257025edf75b9cb7ebc8ab8bfa64.tar.gz
rust-67d1cf112218257025edf75b9cb7ebc8ab8bfa64.zip
introduce an early pass to clear dead blocks
this makes the the MIR assignment pass complete successfully
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/mir_map.rs4
-rw-r--r--src/librustc_mir/transform/clear_dead_blocks.rs62
-rw-r--r--src/librustc_mir/transform/mod.rs1
-rw-r--r--src/librustc_mir/transform/type_check.rs8
4 files changed, 66 insertions, 9 deletions
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index 58b6d69ba5c..68d85dc8394 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 00000000000..88c0116f26d
--- /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 <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);
+    }
+}
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 64e188a3b55..d27c208041f 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 3a891543e80..f4d83cd05e0 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 {