Skip to content

Commit 4a8a552

Browse files
committed
Add DataflowResultsCursor
1 parent 7262e64 commit 4a8a552

File tree

1 file changed

+94
-0
lines changed
  • src/librustc_mir/dataflow

1 file changed

+94
-0
lines changed

src/librustc_mir/dataflow/mod.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,100 @@ pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> {
344344
fn body(&self) -> &'a Body<'tcx>;
345345
}
346346

347+
/// Allows iterating dataflow results in a flexible and reasonably fast way.
348+
#[derive(Clone)]
349+
pub struct DataflowResultsCursor<'mir, 'tcx, BD, DR>
350+
where
351+
BD: BitDenotation<'tcx>,
352+
DR: Borrow<DataflowResults<'tcx, BD>>,
353+
{
354+
flow_state: FlowAtLocation<'tcx, BD, DR>,
355+
356+
// The statement (or terminator) whose effect has been reconstructed in
357+
// flow_state.
358+
curr_loc: Option<Location>,
359+
360+
body: &'mir Body<'tcx>,
361+
}
362+
363+
pub type DataflowResultsRefCursor<'mir, 'tcx, 'flow, BD> =
364+
DataflowResultsCursor<'mir, 'tcx, BD, &'flow DataflowResults<'tcx, BD>>;
365+
366+
impl<'mir, 'tcx, BD, DR> DataflowResultsCursor<'mir, 'tcx, BD, DR>
367+
where
368+
BD: BitDenotation<'tcx>,
369+
DR: Borrow<DataflowResults<'tcx, BD>>,
370+
{
371+
pub fn new(result: DR, body: &'mir Body<'tcx>) -> Self {
372+
DataflowResultsCursor {
373+
flow_state: FlowAtLocation::new(result),
374+
curr_loc: None,
375+
body,
376+
}
377+
}
378+
379+
/// Seek to the given location in MIR. This method is fast if you are
380+
/// traversing your MIR statements in order.
381+
///
382+
/// After calling `seek`, the current state will reflect all effects up to
383+
/// and including the `before_statement_effect` of the statement at location
384+
/// `loc`. The `statement_effect` of the statement at `loc` will be
385+
/// available as the current effect (see e.g. `each_gen_bit`).
386+
///
387+
/// If `loc.statement_index` equals the number of statements in the block,
388+
/// we will reconstruct the terminator effect in the same way as described
389+
/// above.
390+
pub fn seek(&mut self, loc: Location) {
391+
if self.curr_loc.map(|cur| loc == cur).unwrap_or(false) {
392+
return;
393+
}
394+
395+
let start_index;
396+
let should_reset = match self.curr_loc {
397+
None => true,
398+
Some(cur)
399+
if loc.block != cur.block || loc.statement_index < cur.statement_index => true,
400+
_ => false,
401+
};
402+
if should_reset {
403+
self.flow_state.reset_to_entry_of(loc.block);
404+
start_index = 0;
405+
} else {
406+
let curr_loc = self.curr_loc.unwrap();
407+
start_index = curr_loc.statement_index;
408+
// Apply the effect from the last seek to the current state.
409+
self.flow_state.apply_local_effect(curr_loc);
410+
}
411+
412+
for stmt in start_index..loc.statement_index {
413+
let mut stmt_loc = loc;
414+
stmt_loc.statement_index = stmt;
415+
self.flow_state.reconstruct_statement_effect(stmt_loc);
416+
self.flow_state.apply_local_effect(stmt_loc);
417+
}
418+
419+
if loc.statement_index == self.body[loc.block].statements.len() {
420+
self.flow_state.reconstruct_terminator_effect(loc);
421+
} else {
422+
self.flow_state.reconstruct_statement_effect(loc);
423+
}
424+
self.curr_loc = Some(loc);
425+
}
426+
427+
/// Return whether the current state contains bit `x`.
428+
pub fn contains(&self, x: BD::Idx) -> bool {
429+
self.flow_state.contains(x)
430+
}
431+
432+
/// Iterate over each `gen` bit in the current effect (invoke `seek` first).
433+
pub fn each_gen_bit<F>(&self, f: F)
434+
where
435+
F: FnMut(BD::Idx),
436+
{
437+
self.flow_state.each_gen_bit(f)
438+
}
439+
}
440+
347441
pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location,
348442
analysis: &T,
349443
result: &DataflowResults<'tcx, T>,

0 commit comments

Comments
 (0)