diff options
| -rw-r--r-- | src/librustc_mir/util/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustc_mir/util/storage.rs | 42 |
2 files changed, 43 insertions, 0 deletions
diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index bb9d168d919..3e501193e8d 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -3,6 +3,7 @@ pub mod borrowck_errors; pub mod def_use; pub mod elaborate_drops; pub mod patch; +pub mod storage; mod alignment; pub mod collect_writes; diff --git a/src/librustc_mir/util/storage.rs b/src/librustc_mir/util/storage.rs new file mode 100644 index 00000000000..2ce9bed794d --- /dev/null +++ b/src/librustc_mir/util/storage.rs @@ -0,0 +1,42 @@ +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::{self, Local}; + +/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations. +/// +/// These locals have fixed storage for the duration of the body. +// +// FIXME: Currently, we need to traverse the entire MIR to compute this. We should instead store it +// as a field in the `LocalDecl` for each `Local`. +#[derive(Debug, Clone)] +pub struct AlwaysLiveLocals(BitSet<Local>); + +impl AlwaysLiveLocals { + pub fn new(body: &mir::Body<'tcx>) -> Self { + let mut locals = BitSet::new_filled(body.local_decls.len()); + + // FIXME: Use a visitor for this when `visit_body` can take a plain `Body`. + for block in body.basic_blocks().iter() { + for stmt in &block.statements { + if let mir::StatementKind::StorageLive(l) | mir::StatementKind::StorageDead(l) = + stmt.kind + { + locals.remove(l); + } + } + } + + AlwaysLiveLocals(locals) + } + + pub fn into_inner(self) -> BitSet<Local> { + self.0 + } +} + +impl std::ops::Deref for AlwaysLiveLocals { + type Target = BitSet<Local>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} |
