]>
git.proxmox.com Git - rustc.git/blob - src/librustc_mir/transform/clear_dead_blocks.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! A pass that erases the contents of dead blocks. This pass must
12 //! run before any analysis passes because some of the dead blocks
15 //! The main problem is that typeck lets most blocks whose end is not
16 //! reachable have an arbitrary return type, rather than having the
17 //! usual () return type (as a note, typeck's notion of reachability
18 //! is in fact slightly weaker than MIR CFG reachability - see #31617).
20 //! A standard example of the situation is:
23 //! let _a: char = { return; };
27 //! Here the block (`{ return; }`) has the return type `char`,
28 //! rather than `()`, but the MIR we naively generate still contains
29 //! the `_a = ()` write in the unreachable block "after" the return.
31 //! As we have to run this pass even when we want to debug the MIR,
32 //! this pass just replaces the blocks with empty "return" blocks
33 //! and does not renumber anything.
35 use rustc
::middle
::infer
;
36 use rustc
::mir
::repr
::*;
37 use rustc
::mir
::transform
::MirPass
;
39 pub struct ClearDeadBlocks
;
41 impl ClearDeadBlocks
{
42 pub fn new() -> ClearDeadBlocks
{
46 fn clear_dead_blocks(&self, mir
: &mut Mir
) {
47 let mut seen
= vec
![false; mir
.basic_blocks
.len()];
49 // These blocks are always required.
50 seen
[START_BLOCK
.index()] = true;
51 seen
[END_BLOCK
.index()] = true;
53 let mut worklist
= vec
![START_BLOCK
];
54 while let Some(bb
) = worklist
.pop() {
55 for succ
in mir
.basic_block_data(bb
).terminator().successors().iter() {
56 if !seen
[succ
.index()] {
57 seen
[succ
.index()] = true;
63 for (n
, (block
, seen
)) in mir
.basic_blocks
.iter_mut().zip(seen
).enumerate() {
65 info
!("clearing block #{}: {:?}", n
, block
);
66 *block
= BasicBlockData
{
68 terminator
: Some(Terminator
::Return
),
76 impl MirPass
for ClearDeadBlocks
{
77 fn run_on_mir
<'a
, 'tcx
>(&mut self, mir
: &mut Mir
<'tcx
>, _
: &infer
::InferCtxt
<'a
, 'tcx
>)
79 self.clear_dead_blocks(mir
);