diff options
| author | Felix S. Klock II <pnkfelix@pnkfx.org> | 2017-05-22 13:06:51 +0200 |
|---|---|---|
| committer | Felix S. Klock II <pnkfelix@pnkfx.org> | 2017-06-12 13:06:42 +0200 |
| commit | 0a5211e80951eeb89e6f8e9e10b31398904d8d76 (patch) | |
| tree | 58c2a6053e6d09593ac85af1bea8e2a273f96090 /src/librustc_mir/transform | |
| parent | 1d315cf7da85911dfa239331fab30607ce2d1dce (diff) | |
| download | rust-0a5211e80951eeb89e6f8e9e10b31398904d8d76.tar.gz rust-0a5211e80951eeb89e6f8e9e10b31398904d8d76.zip | |
Add post-pass to remove EndRegions of unborrowed extents.
Diffstat (limited to 'src/librustc_mir/transform')
| -rw-r--r-- | src/librustc_mir/transform/clean_end_regions.rs | 84 | ||||
| -rw-r--r-- | src/librustc_mir/transform/mod.rs | 1 |
2 files changed, 85 insertions, 0 deletions
diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs new file mode 100644 index 00000000000..36125f94543 --- /dev/null +++ b/src/librustc_mir/transform/clean_end_regions.rs @@ -0,0 +1,84 @@ +// Copyright 2017 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. + +//! This module provides one pass, `CleanEndRegions`, that reduces the +//! set of `EndRegion` statements in the MIR. +//! +//! The "pass" is actually implemented as two traversals (aka visits) +//! of the input MIR. The first traversal, `GatherBorrowedRegions`, +//! finds all of the regions in the MIR that are involved in a borrow. +//! +//! The second traversal, `DeleteTrivialEndRegions`, walks over the +//! MIR and removes any `EndRegion` that is applied to a region that +//! was not seen in the previous pass. + +use rustc_data_structures::fx::FxHashSet; + +use rustc::middle::region::CodeExtent; +use rustc::mir::transform::{MirPass, MirSource}; +use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind}; +use rustc::mir::visit::{MutVisitor, Visitor}; +use rustc::ty::{RegionKind, TyCtxt}; + +pub struct CleanEndRegions; + +struct GatherBorrowedRegions { + seen_regions: FxHashSet<CodeExtent>, +} + +struct DeleteTrivialEndRegions<'a> { + seen_regions: &'a FxHashSet<CodeExtent>, +} + +impl MirPass for CleanEndRegions { + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _source: MirSource, + mir: &mut Mir<'tcx>) { + let mut gather = GatherBorrowedRegions { seen_regions: FxHashSet() }; + gather.visit_mir(mir); + + let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions }; + delete.visit_mir(mir); + } +} + +impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions { + fn visit_rvalue(&mut self, + rvalue: &Rvalue<'tcx>, + location: Location) { + if let Rvalue::Ref(r, _, _) = *rvalue { + if let RegionKind::ReScope(ce) = *r { + self.seen_regions.insert(ce); + } + } + self.super_rvalue(rvalue, location); + } +} + +impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> { + fn visit_statement(&mut self, + block: BasicBlock, + statement: &mut Statement<'tcx>, + location: Location) { + let mut delete_it = false; + + if let StatementKind::EndRegion(ref extent) = statement.kind { + if !self.seen_regions.contains(extent) { + delete_it = true; + } + } + + if delete_it { + statement.kind = StatementKind::Nop; + } + self.super_statement(block, statement, location); + } +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index fcea5d4c860..4594c611d59 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -24,6 +24,7 @@ use syntax::ast; use syntax_pos::{DUMMY_SP, Span}; use transform; +pub mod clean_end_regions; pub mod simplify_branches; pub mod simplify; pub mod erase_regions; |
