Skip to content

Commit 1d737fb

Browse files
Use MaybeBorrowedLocals for generator analyses
It should have the same semantics as `HaveBeenBorrowedLocals`
1 parent 9972502 commit 1d737fb

File tree

2 files changed

+27
-39
lines changed

2 files changed

+27
-39
lines changed

src/librustc_mir/dataflow/impls/storage_liveness.rs

+20-26
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
pub use super::*;
22

3+
use crate::dataflow::generic::{Results, ResultsRefCursor};
34
use crate::dataflow::BitDenotation;
4-
use crate::dataflow::HaveBeenBorrowedLocals;
5-
use crate::dataflow::{DataflowResults, DataflowResultsCursor, DataflowResultsRefCursor};
5+
use crate::dataflow::MaybeBorrowedLocals;
66
use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
77
use rustc::mir::*;
88
use std::cell::RefCell;
@@ -69,22 +69,23 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
6969
const BOTTOM_VALUE: bool = false;
7070
}
7171

72+
type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>;
73+
7274
/// Dataflow analysis that determines whether each local requires storage at a
7375
/// given location; i.e. whether its storage can go away without being observed.
7476
pub struct RequiresStorage<'mir, 'tcx> {
7577
body: ReadOnlyBodyAndCache<'mir, 'tcx>,
76-
borrowed_locals:
77-
RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
78+
borrowed_locals: RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
7879
}
7980

8081
impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
8182
pub fn new(
8283
body: ReadOnlyBodyAndCache<'mir, 'tcx>,
83-
borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
84+
borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>,
8485
) -> Self {
8586
RequiresStorage {
8687
body,
87-
borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, *body)),
88+
borrowed_locals: RefCell::new(ResultsRefCursor::new(*body, borrowed_locals)),
8889
}
8990
}
9091

@@ -111,11 +112,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
111112
}
112113

113114
fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {
114-
// If we borrow or assign to a place then it needs storage for that
115-
// statement.
116-
self.check_for_borrow(sets, loc);
117-
118115
let stmt = &self.body[loc.block].statements[loc.statement_index];
116+
117+
// If a place is borrowed in a statement, it needs storage for that statement.
118+
self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc);
119+
120+
// If a place is assigned to in a statement, it needs storage for that statement.
119121
match stmt.kind {
120122
StatementKind::StorageDead(l) => sets.kill(l),
121123
StatementKind::Assign(box (ref place, _))
@@ -138,12 +140,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
138140
}
139141

140142
fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
141-
self.check_for_borrow(sets, loc);
143+
let terminator = self.body[loc.block].terminator();
142144

143-
if let TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } =
144-
self.body[loc.block].terminator().kind
145-
{
146-
sets.gen(local);
145+
// If a place is borrowed in a terminator, it needs storage for that terminator.
146+
self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc);
147+
148+
if let TerminatorKind::Call { destination: Some((place, _)), .. } = terminator.kind {
149+
sets.gen(place.local);
147150
}
148151
}
149152

@@ -179,14 +182,6 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
179182
let mut visitor = MoveVisitor { sets, borrowed_locals: &self.borrowed_locals };
180183
visitor.visit_location(self.body, loc);
181184
}
182-
183-
/// Gen locals that are newly borrowed. This includes borrowing any part of
184-
/// a local (we rely on this behavior of `HaveBeenBorrowedLocals`).
185-
fn check_for_borrow(&self, sets: &mut GenKillSet<Local>, loc: Location) {
186-
let mut borrowed_locals = self.borrowed_locals.borrow_mut();
187-
borrowed_locals.seek(loc);
188-
borrowed_locals.each_gen_bit(|l| sets.gen(l));
189-
}
190185
}
191186

192187
impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
@@ -195,16 +190,15 @@ impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
195190
}
196191

197192
struct MoveVisitor<'a, 'mir, 'tcx> {
198-
borrowed_locals:
199-
&'a RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
193+
borrowed_locals: &'a RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
200194
sets: &'a mut GenKillSet<Local>,
201195
}
202196

203197
impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> {
204198
fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) {
205199
if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
206200
let mut borrowed_locals = self.borrowed_locals.borrow_mut();
207-
borrowed_locals.seek(loc);
201+
borrowed_locals.seek_before(loc);
208202
if !borrowed_locals.contains(*local) {
209203
self.sets.kill(*local);
210204
}

src/librustc_mir/transform/generator.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@
4949
//! For generators with state 1 (returned) and state 2 (poisoned) it does nothing.
5050
//! Otherwise it drops all the values in scope at the last suspension point.
5151
52+
use crate::dataflow::generic::{Analysis, ResultsCursor};
5253
use crate::dataflow::{do_dataflow, DataflowResultsCursor, DebugFormatted};
5354
use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation};
54-
use crate::dataflow::{HaveBeenBorrowedLocals, MaybeStorageLive, RequiresStorage};
55+
use crate::dataflow::{MaybeBorrowedLocals, MaybeStorageLive, RequiresStorage};
5556
use crate::transform::no_landing_pads::no_landing_pads;
5657
use crate::transform::simplify;
5758
use crate::transform::{MirPass, MirSource};
@@ -471,17 +472,10 @@ fn locals_live_across_suspend_points(
471472

472473
// Calculate the MIR locals which have been previously
473474
// borrowed (even if they are still active).
474-
let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body_ref);
475-
let borrowed_locals_results = do_dataflow(
476-
tcx,
477-
body_ref,
478-
def_id,
479-
&[],
480-
&dead_unwinds,
481-
borrowed_locals_analysis,
482-
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]),
483-
);
484-
let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body_ref);
475+
let borrowed_locals_results =
476+
MaybeBorrowedLocals::new().into_engine(tcx, body_ref, def_id).iterate_to_fixpoint();
477+
478+
let mut borrowed_locals_cursor = ResultsCursor::new(body_ref, &borrowed_locals_results);
485479

486480
// Calculate the MIR locals that we actually need to keep storage around
487481
// for.
@@ -521,7 +515,7 @@ fn locals_live_across_suspend_points(
521515
// If a borrow is converted to a raw reference, we must also assume that it lives
522516
// forever. Note that the final liveness is still bounded by the storage liveness
523517
// of the local, which happens using the `intersect` operation below.
524-
borrowed_locals_cursor.seek(loc);
518+
borrowed_locals_cursor.seek_before(loc);
525519
liveness.outs[block].union(borrowed_locals_cursor.get());
526520
}
527521

0 commit comments

Comments
 (0)