diff options
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/mod.rs | 8 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/liveness.rs | 11 | ||||
| -rw-r--r-- | src/librustc_mir/transform/generator.rs | 52 | ||||
| -rw-r--r-- | src/librustc_mir/util/liveness.rs | 69 |
4 files changed, 84 insertions, 56 deletions
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index ba96e7c3b30..72d7b473204 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -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}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, Local}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -208,9 +208,9 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( (regioncx, polonius_output, closure_region_requirements) } -fn dump_mir_results<'a, 'gcx, 'tcx, V: Idx>( +fn dump_mir_results<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, - liveness: &LivenessResults<V>, + liveness: &LivenessResults<Local>, source: MirSource, mir: &Mir<'tcx>, regioncx: &RegionInferenceContext, @@ -406,7 +406,7 @@ impl ToRegionVid for RegionVid { } } -fn live_variable_set<V: Idx>(regular: &LocalSet<V>, drops: &LocalSet<V>) -> String { +fn live_variable_set(regular: &LocalSet<Local>, drops: &LocalSet<Local>) -> String { // sort and deduplicate: let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect(); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 7c0e7941a44..e70c87e8401 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -34,10 +34,10 @@ use super::TypeChecker; /// /// NB. This computation requires normalization; therefore, it must be /// performed before -pub(super) fn generate<'gcx, 'tcx, V: Idx>( +pub(super) fn generate<'gcx, 'tcx>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, - liveness: &LivenessResults<V>, + liveness: &LivenessResults<Local>, flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>, move_data: &MoveData<'tcx>, ) { @@ -55,17 +55,16 @@ pub(super) fn generate<'gcx, 'tcx, V: Idx>( } } -struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> +struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> where 'typeck: 'gen, 'flow: 'gen, 'tcx: 'typeck + 'flow, 'gcx: 'tcx, - V: Idx + 'gen, { cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, - liveness: &'gen LivenessResults<V>, + liveness: &'gen LivenessResults<Local>, flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>, @@ -76,7 +75,7 @@ struct DropData<'tcx> { region_constraint_data: Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>, } -impl<'gen, 'typeck, 'flow, 'gcx, 'tcx, V: Idx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> { +impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> { /// Liveness constraints: /// /// > If a variable V is live at point P, then all regions R in the type of V diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 0b8c7e512fb..f1091e40c77 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -126,14 +126,14 @@ fn self_arg() -> Local { Local::new(1) } -struct SuspensionPoint<V: Idx> { +struct SuspensionPoint { state: u32, resume: BasicBlock, drop: Option<BasicBlock>, - storage_liveness: liveness::LocalSet<V>, + storage_liveness: liveness::LocalSet<Local>, } -struct TransformVisitor<'a, 'tcx: 'a, V: Idx> { +struct TransformVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, state_adt_ref: &'tcx AdtDef, state_substs: &'tcx Substs<'tcx>, @@ -145,16 +145,16 @@ struct TransformVisitor<'a, 'tcx: 'a, V: Idx> { remap: HashMap<Local, (Ty<'tcx>, usize)>, // A map from a suspension point in a block to the locals which have live storage at that point - storage_liveness: HashMap<BasicBlock, liveness::LocalSet<V>>, + storage_liveness: HashMap<BasicBlock, liveness::LocalSet<Local>>, // A list of suspension points, generated during the transform - suspension_points: Vec<SuspensionPoint<V>>, + suspension_points: Vec<SuspensionPoint>, // The original RETURN_PLACE local new_ret_local: Local, } -impl<'a, 'tcx, V: Idx> TransformVisitor<'a, 'tcx, V> { +impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { // Make a GeneratorState rvalue fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> { let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None); @@ -191,7 +191,7 @@ impl<'a, 'tcx, V: Idx> TransformVisitor<'a, 'tcx, V> { } } -impl<'a, 'tcx, V: Idx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx, V> { +impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> { fn visit_local(&mut self, local: &mut Local, _: PlaceContext<'tcx>, @@ -317,9 +317,9 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>, new_ret_local } -struct StorageIgnored<V: Idx>(liveness::LocalSet<V>); +struct StorageIgnored(liveness::LocalSet<Local>); -impl<'tcx, V: Idx> Visitor<'tcx> for StorageIgnored<V> { +impl<'tcx> Visitor<'tcx> for StorageIgnored { fn visit_statement(&mut self, _block: BasicBlock, statement: &Statement<'tcx>, @@ -332,9 +332,9 @@ impl<'tcx, V: Idx> Visitor<'tcx> for StorageIgnored<V> { } } -struct BorrowedLocals<V: Idx>(liveness::LocalSet<V>); +struct BorrowedLocals(liveness::LocalSet<Local>); -fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLocals<V>) { +fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { match *place { Place::Local(l) => { locals.0.add(&l); }, Place::Static(..) => (), @@ -349,7 +349,7 @@ fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLoca } } -impl<'tcx, V: Idx> Visitor<'tcx> for BorrowedLocals<V> { +impl<'tcx> Visitor<'tcx> for BorrowedLocals { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { @@ -361,12 +361,12 @@ impl<'tcx, V: Idx> Visitor<'tcx> for BorrowedLocals<V> { } } -fn locals_live_across_suspend_points<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, source: MirSource, movable: bool) -> - (liveness::LocalSet<V>, - HashMap<BasicBlock, liveness::LocalSet<V>>) { + (liveness::LocalSet<Local>, + HashMap<BasicBlock, liveness::LocalSet<Local>>) { let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); @@ -460,7 +460,7 @@ fn locals_live_across_suspend_points<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tc (set, storage_liveness_map) } -fn compute_layout<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, upvars: Vec<Ty<'tcx>>, interior: Ty<'tcx>, @@ -468,7 +468,7 @@ fn compute_layout<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) -> (HashMap<Local, (Ty<'tcx>, usize)>, GeneratorLayout<'tcx>, - HashMap<BasicBlock, liveness::LocalSet<V>>) + HashMap<BasicBlock, liveness::LocalSet<Local>>) { // Use a liveness analysis to compute locals which are live across a suspension point let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx, @@ -524,10 +524,10 @@ fn compute_layout<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (remap, layout, storage_liveness) } -fn insert_switch<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>, cases: Vec<(u32, BasicBlock)>, - transform: &TransformVisitor<'a, 'tcx, V>, + transform: &TransformVisitor<'a, 'tcx>, default: TerminatorKind<'tcx>) { let default_block = insert_term_block(mir, default); @@ -608,9 +608,9 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn create_generator_drop_shim<'a, 'tcx, V: Idx>( +fn create_generator_drop_shim<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - transform: &TransformVisitor<'a, 'tcx, V>, + transform: &TransformVisitor<'a, 'tcx>, def_id: DefId, source: MirSource, gen_ty: Ty<'tcx>, @@ -719,9 +719,9 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert_block } -fn create_generator_resume_function<'a, 'tcx, V: Idx>( +fn create_generator_resume_function<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - transform: TransformVisitor<'a, 'tcx, V>, + transform: TransformVisitor<'a, 'tcx>, def_id: DefId, source: MirSource, mir: &mut Mir<'tcx>) { @@ -790,10 +790,10 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock { drop_clean } -fn create_cases<'a, 'tcx, F, V: Idx>(mir: &mut Mir<'tcx>, - transform: &TransformVisitor<'a, 'tcx, V>, +fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>, + transform: &TransformVisitor<'a, 'tcx>, target: F) -> Vec<(u32, BasicBlock)> - where F: Fn(&SuspensionPoint<V>) -> Option<BasicBlock> { + where F: Fn(&SuspensionPoint) -> Option<BasicBlock> { let source_info = source_info(mir); transform.suspension_points.iter().filter_map(|point| { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 5c1b92b672f..811e0e55909 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -40,6 +40,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::work_queue::WorkQueue; use util::pretty::{dump_enabled, write_basic_block, write_mir_intro}; use rustc::ty::item_path; +use rustc::mir::Local; use rustc::mir::visit::MirVisitable; use std::path::{Path, PathBuf}; use std::fs; @@ -61,6 +62,28 @@ pub struct LivenessResult<V: Idx> { pub outs: IndexVec<BasicBlock, LocalSet<V>>, } +trait LiveVariableMap { + type LiveVar; + + fn from_local(&self, local: Local) -> Option<Self::LiveVar>; + fn from_live_var(&self, local: Self::LiveVar) -> Local; +} + +#[derive(Eq, PartialEq, Clone)] +struct IdentityMap; + +impl LiveVariableMap for IdentityMap { + type LiveVar = Local; + + fn from_local(&self, local: Local) -> Option<Self::LiveVar> { + Some(local) + } + + fn from_live_var(&self, local: Self::LiveVar) -> Local { + local + } +} + #[derive(Copy, Clone, Debug)] pub struct LivenessMode { /// If true, then we will consider "regular uses" of a variable to be live. @@ -91,7 +114,7 @@ pub struct LivenessResults<V: Idx> { } impl<V: Idx> LivenessResults<V> { - pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults<V> { + pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &dyn LiveVariableMap<LiveVar = V>) -> LivenessResults<V> { LivenessResults { regular: liveness_of_locals( &mir, @@ -187,6 +210,7 @@ where V:Idx defs_uses: DefsUses { defs: LocalSet::new_empty(locals), uses: LocalSet::new_empty(locals), + map: &IdentityMap {}, }, }; // Visit the various parts of the basic block in reverse. If we go @@ -283,25 +307,26 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti } } -struct DefsUsesVisitor<V: Idx> { +struct DefsUsesVisitor<'lv> { mode: LivenessMode, - defs_uses: DefsUses<V>, + defs_uses: DefsUses<'lv>, } #[derive(Eq, PartialEq, Clone)] -struct DefsUses<V: Idx> +struct DefsUses<'lv> { - defs: LocalSet<V>, - uses: LocalSet<V>, + defs: LocalSet<Local>, + uses: LocalSet<Local>, + map: &'lv dyn LiveVariableMap<LiveVar=Local>, } -impl<V: Idx> DefsUses<V> { +impl<'lv> DefsUses<'lv> { fn clear(&mut self) { self.uses.clear(); self.defs.clear(); } - fn apply(&self, bits: &mut LocalSet<V>) -> bool { + fn apply(&self, bits: &mut LocalSet<Local>) -> bool { bits.subtract(&self.defs) | bits.union(&self.uses) } @@ -315,8 +340,10 @@ impl<V: Idx> DefsUses<V> { // X = 5 // // Defs = {}, Uses = {X} // use(X) - self.uses.remove(&index); - self.defs.add(&index); + if let Some(v_index) = self.map.from_local(index) { + self.uses.remove(&v_index); + self.defs.add(&v_index); + } } fn add_use(&mut self, index: Local) { @@ -330,22 +357,23 @@ impl<V: Idx> DefsUses<V> { // X = 5 // // Defs = {}, Uses = {X} // use(X) - self.defs.remove(&index); - self.uses.add(&index); + if let Some(v_index) = self.map.from_local(index) { + self.defs.remove(&v_index); + self.uses.add(&v_index); + } } } -impl<V> DefsUsesVisitor<V> -where V: Idx +impl<'lv> DefsUsesVisitor<'lv> { /// Update `bits` with the effects of `value` and call `callback`. We /// should always visit in reverse order. This method assumes that we have /// not visited anything before; if you have, clear `bits` first. fn update_bits_and_do_callback<'tcx, OP>(&mut self, location: Location, - value: &impl MirVisitable<'tcx>, bits: &mut LocalSet<V>, + value: &impl MirVisitable<'tcx>, bits: &mut LocalSet<Local>, callback: &mut OP) where - OP: FnMut(Location, &LocalSet<V>), + OP: FnMut(Location, &LocalSet<Local>), { value.apply(location, self); self.defs_uses.apply(bits); @@ -353,7 +381,7 @@ where V: Idx } } -impl<'tcx, V: Idx> Visitor<'tcx> for DefsUsesVisitor<V> { +impl<'tcx, 'lv> Visitor<'tcx> for DefsUsesVisitor<'lv> { fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) { match categorize(context, self.mode) { Some(DefUse::Def) => { @@ -369,12 +397,13 @@ impl<'tcx, V: Idx> Visitor<'tcx> for DefsUsesVisitor<V> { } } -fn block<'tcx, V: Idx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses<V> { +fn block<'tcx, 'lv>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses<'lv> { let mut visitor = DefsUsesVisitor { mode, defs_uses: DefsUses { defs: LocalSet::new_empty(locals), uses: LocalSet::new_empty(locals), + map: &IdentityMap {}, }, }; @@ -398,7 +427,7 @@ pub fn dump_mir<'a, 'tcx, V: Idx>( pass_name: &str, source: MirSource, mir: &Mir<'tcx>, - result: &LivenessResult<V>, + result: &LivenessResult<Local>, ) { if !dump_enabled(tcx, pass_name, source) { return; @@ -442,7 +471,7 @@ pub fn write_mir_fn<'a, 'tcx, V :Idx>( ) -> io::Result<()> { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - let print = |w: &mut dyn Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| { + let print = |w: &mut dyn Write, prefix, result: &IndexVec<BasicBlock, LocalSet<V>>| { let live: Vec<String> = mir.local_decls .indices() .filter(|i| result[block].contains(i)) |
