add LocalWithRegion NllLivenessMap

This commit is contained in:
dylan_DPC 2018-07-18 22:31:04 +05:30
parent 43b69c2777
commit 0d847ec1ab
8 changed files with 76 additions and 36 deletions

View file

@ -52,7 +52,7 @@ pub mod traversal;
pub mod visit;
/// Types for locals
type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;
type LocalDecls<'tcx> = IndexVec<LocalWithRegion, LocalDecl<'tcx>>;
pub trait HasLocalDecls<'tcx> {
fn local_decls(&self) -> &LocalDecls<'tcx>;
@ -141,7 +141,7 @@ impl<'tcx> Mir<'tcx> {
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
promoted: IndexVec<Promoted, Mir<'tcx>>,
yield_ty: Option<Ty<'tcx>>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
local_decls: IndexVec<LocalWithRegion, LocalDecl<'tcx>>,
arg_count: usize,
upvar_decls: Vec<UpvarDecl>,
span: Span,
@ -209,7 +209,7 @@ impl<'tcx> Mir<'tcx> {
}
#[inline]
pub fn local_kind(&self, local: Local) -> LocalKind {
pub fn local_kind(&self, local: LocalWithRegion) -> LocalKind {
let index = local.0 as usize;
if index == 0 {
debug_assert!(
@ -234,9 +234,9 @@ impl<'tcx> Mir<'tcx> {
/// Returns an iterator over all temporaries.
#[inline]
pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = LocalWithRegion> + 'a {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let local = LocalWithRegion::new(index);
if self.local_decls[local].is_user_variable.is_some() {
None
} else {
@ -247,9 +247,9 @@ impl<'tcx> Mir<'tcx> {
/// Returns an iterator over all user-declared locals.
#[inline]
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = LocalWithRegion> + 'a {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let local = LocalWithRegion::new(index);
if self.local_decls[local].is_user_variable.is_some() {
Some(local)
} else {
@ -260,9 +260,9 @@ impl<'tcx> Mir<'tcx> {
/// Returns an iterator over all user-declared mutable arguments and locals.
#[inline]
pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = LocalWithRegion> + 'a {
(1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let local = LocalWithRegion::new(index);
let decl = &self.local_decls[local];
if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
&& decl.mutability == Mutability::Mut
@ -2932,3 +2932,5 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> {
}
}
}
newtype_index!(LocalWithRegion);

View file

@ -146,7 +146,7 @@ macro_rules! make_mir_visitor {
fn visit_user_assert_ty(&mut self,
c_ty: & $($mutability)* CanonicalTy<'tcx>,
local: & $($mutability)* Local,
local: & $($mutability)* LocalWithRegion,
location: Location) {
self.super_user_assert_ty(c_ty, local, location);
}
@ -250,13 +250,13 @@ macro_rules! make_mir_visitor {
}
fn visit_local_decl(&mut self,
local: Local,
local: LocalWithRegion,
local_decl: & $($mutability)* LocalDecl<'tcx>) {
self.super_local_decl(local, local_decl);
}
fn visit_local(&mut self,
_local: & $($mutability)* Local,
_local: & $($mutability)* LocalWithRegion,
_context: PlaceContext<'tcx>,
_location: Location) {
}
@ -632,7 +632,7 @@ macro_rules! make_mir_visitor {
fn super_user_assert_ty(&mut self,
_c_ty: & $($mutability)* CanonicalTy<'tcx>,
local: & $($mutability)* Local,
local: & $($mutability)* LocalWithRegion,
location: Location) {
self.visit_local(local, PlaceContext::Validate, location);
}
@ -708,7 +708,7 @@ macro_rules! make_mir_visitor {
}
fn super_local_decl(&mut self,
local: Local,
local: LocalWithRegion,
local_decl: & $($mutability)* LocalDecl<'tcx>) {
let LocalDecl {
mutability: _,

View file

@ -278,7 +278,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
// Note that this set is expected to be small - only upvars from closures
// would have a chance of erroneously adding non-user-defined mutable vars
// to the set.
let temporary_used_locals: FxHashSet<Local> = mbcx
let temporary_used_locals: FxHashSet<LocalWithRegion> = mbcx
.used_mut
.iter()
.filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())

View file

@ -19,7 +19,7 @@ use dataflow::FlowAtLocation;
use dataflow::MaybeInitializedPlaces;
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, Local};
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, LocalWithRegion};
use rustc::ty::{self, RegionKind, RegionVid};
use rustc::util::nodemap::FxHashMap;
use std::collections::BTreeSet;
@ -30,7 +30,7 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::str::FromStr;
use transform::MirSource;
use util::liveness::{IdentityMap, LivenessResults, LocalSet};
use util::liveness::{IdentityMap, LivenessResults, LocalSet, NllLivenessMap};
use self::mir_util::PassWhere;
use polonius_engine::{Algorithm, Output};
@ -103,7 +103,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
let elements = &Rc::new(RegionValueElements::new(mir, universal_regions.len()));
// Run the MIR type-checker.
let liveness = &LivenessResults::compute(mir, &IdentityMap::new(mir));
let liveness_map = NllLivenessMap::compute(&mir);
let liveness = LivenessResults::compute(mir, &liveness_map);
let constraint_sets = type_check::type_check(
infcx,
param_env,
@ -193,7 +194,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
// write unit-tests, as well as helping with debugging.
dump_mir_results(
infcx,
liveness,
&liveness,
MirSource::item(def_id),
&mir,
&regioncx,
@ -209,7 +210,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
fn dump_mir_results<'a, 'gcx, 'tcx>(
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
liveness: &LivenessResults<Local>,
liveness: &LivenessResults<LocalWithRegion>,
source: MirSource,
mir: &Mir<'tcx>,
regioncx: &RegionInferenceContext,
@ -407,7 +408,7 @@ impl ToRegionVid for RegionVid {
}
}
fn live_variable_set(regular: &LocalSet<Local>, drops: &LocalSet<Local>) -> String {
fn live_variable_set(regular: &LocalSet<LocalWithRegion>, drops: &LocalSet<LocalWithRegion>) -> String {
// sort and deduplicate:
let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect();

View file

@ -13,7 +13,7 @@ use dataflow::move_paths::{HasMoveData, MoveData};
use dataflow::MaybeInitializedPlaces;
use dataflow::{FlowAtLocation, FlowsAtLocation};
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::mir::Local;
use rustc::mir::{Local, LocalWithRegion};
use rustc::mir::{BasicBlock, Location, Mir};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc::traits::query::type_op::outlives::DropckOutlives;
@ -36,7 +36,7 @@ use super::TypeChecker;
pub(super) fn generate<'gcx, 'tcx>(
cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
liveness: &LivenessResults<Local>,
liveness: &LivenessResults<LocalWithRegion>,
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
) {
@ -64,7 +64,7 @@ where
{
cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>,
mir: &'gen Mir<'tcx>,
liveness: &'gen LivenessResults<Local>,
liveness: &'gen LivenessResults<LocalWithRegion>,
flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>,
move_data: &'gen MoveData<'tcx>,
drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>,
@ -93,7 +93,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
}
});
let mut all_live_locals: Vec<(Location, Vec<Local>)> = vec![];
let mut all_live_locals: Vec<(Location, Vec<LocalWithRegion>)> = vec![];
self.liveness
.drop
.simulate_block(self.mir, bb, self.map, |location, live_locals| {

View file

@ -108,8 +108,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
mir_def_id: DefId,
universal_regions: &UniversalRegions<'tcx>,
location_table: &LocationTable,
borrow_set: &BorrowSet<'tcx>,
liveness: &LivenessResults,
liveness: &LivenessResults<LocalWithRegion>,
all_facts: &mut Option<AllFacts>,
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,

View file

@ -37,18 +37,18 @@ impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
}
impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
type Idx = Local;
type Idx = LocalWithRegion;
fn name() -> &'static str { "has_been_borrowed_locals" }
fn bits_per_block(&self) -> usize {
self.mir.local_decls.len()
}
fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
fn start_block_effect(&self, _sets: &mut IdxSet<LocalWithRegion>) {
// Nothing is borrowed on function entry
}
fn statement_effect(&self,
sets: &mut BlockSets<Local>,
sets: &mut BlockSets<LocalWithRegion>,
loc: Location) {
BorrowedLocalsVisitor {
sets,
@ -56,7 +56,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
}
fn terminator_effect(&self,
sets: &mut BlockSets<Local>,
sets: &mut BlockSets<LocalWithRegion>,
loc: Location) {
BorrowedLocalsVisitor {
sets,
@ -64,7 +64,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
}
fn propagate_call_return(&self,
_in_out: &mut IdxSet<Local>,
_in_out: &mut IdxSet<LocalWithRegion>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
_dest_place: &mir::Place) {
@ -87,10 +87,10 @@ impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
}
struct BorrowedLocalsVisitor<'b, 'c: 'b> {
sets: &'b mut BlockSets<'c, Local>,
sets: &'b mut BlockSets<'c, LocalWithRegion>,
}
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<LocalWithRegion> {
match *place {
Place::Local(l) => Some(l),
Place::Static(..) => None,

View file

@ -37,8 +37,7 @@ use rustc::mir::visit::MirVisitable;
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::Local;
use rustc::mir::*;
use rustc::ty::item_path;
use rustc::ty::TyCtxt;
use rustc::ty::{item_path, TyCtxt, TypeFoldable};
use rustc_data_structures::indexed_set::IdxSetBuf;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::work_queue::WorkQueue;
@ -545,3 +544,42 @@ pub fn write_mir_fn<'a, 'tcx, V: Idx>(
writeln!(w, "}}")?;
Ok(())
}
crate struct NllLivenessMap {
pub from_local: IndexVec<Local, Option<LocalWithRegion>>,
pub to_local: IndexVec<LocalWithRegion, Local>,
}
impl LiveVariableMap for NllLivenessMap {
type LiveVar = LocalWithRegion;
fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
self.from_local[local]
}
fn from_live_var(&self, local: Self::LiveVar) -> Local {
self.to_local[local]
}
fn num_variables(&self) -> usize {
self.to_local.len()
}
}
impl NllLivenessMap {
pub fn compute(mir: &Mir) -> Self {
let mut to_local = IndexVec::default();
let from_local: IndexVec<_,_> = mir.local.decls.iter_enumerated.map(|local, local_decl| {
if local_decl.ty.has_free_regions() {
Some(to_local.push(local))
}
else {
None
}
}).collect();
Self { from_local, to_local }
}
}