use std::borrow::Borrow;
use rustc_middle::mir::{self, BasicBlock, Location};
use super::{Analysis, Direction, EntrySets, Results};
pub fn visit_results<'mir, 'tcx, F, R>(
body: &'mir mir::Body<'tcx>,
blocks: impl IntoIterator<Item = BasicBlock>,
results: &mut R,
vis: &mut impl ResultsVisitor<'mir, 'tcx, R, FlowState = F>,
) where
R: ResultsVisitable<'tcx, FlowState = F>,
{
let mut state = results.new_flow_state(body);
#[cfg(debug_assertions)]
let reachable_blocks = mir::traversal::reachable_as_bitset(body);
for block in blocks {
#[cfg(debug_assertions)]
assert!(reachable_blocks.contains(block));
let block_data = &body[block];
R::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
}
}
pub trait ResultsVisitor<'mir, 'tcx, R> {
type FlowState;
fn visit_block_start(
&mut self,
_results: &mut R,
_state: &Self::FlowState,
_block_data: &'mir mir::BasicBlockData<'tcx>,
_block: BasicBlock,
) {
}
fn visit_statement_before_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::FlowState,
_statement: &'mir mir::Statement<'tcx>,
_location: Location,
) {
}
fn visit_statement_after_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::FlowState,
_statement: &'mir mir::Statement<'tcx>,
_location: Location,
) {
}
fn visit_terminator_before_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::FlowState,
_terminator: &'mir mir::Terminator<'tcx>,
_location: Location,
) {
}
fn visit_terminator_after_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::FlowState,
_terminator: &'mir mir::Terminator<'tcx>,
_location: Location,
) {
}
fn visit_block_end(
&mut self,
_results: &mut R,
_state: &Self::FlowState,
_block_data: &'mir mir::BasicBlockData<'tcx>,
_block: BasicBlock,
) {
}
}
pub trait ResultsVisitable<'tcx> {
type Direction: Direction;
type FlowState;
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState;
fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock);
fn reconstruct_before_statement_effect(
&mut self,
state: &mut Self::FlowState,
statement: &mir::Statement<'tcx>,
location: Location,
);
fn reconstruct_statement_effect(
&mut self,
state: &mut Self::FlowState,
statement: &mir::Statement<'tcx>,
location: Location,
);
fn reconstruct_before_terminator_effect(
&mut self,
state: &mut Self::FlowState,
terminator: &mir::Terminator<'tcx>,
location: Location,
);
fn reconstruct_terminator_effect(
&mut self,
state: &mut Self::FlowState,
terminator: &mir::Terminator<'tcx>,
location: Location,
);
}
impl<'tcx, A, E> ResultsVisitable<'tcx> for Results<'tcx, A, E>
where
A: Analysis<'tcx>,
E: Borrow<EntrySets<'tcx, A>>,
{
type FlowState = A::Domain;
type Direction = A::Direction;
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
self.analysis.bottom_value(body)
}
fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
state.clone_from(self.entry_set_for_block(block));
}
fn reconstruct_before_statement_effect(
&mut self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
) {
self.analysis.apply_before_statement_effect(state, stmt, loc);
}
fn reconstruct_statement_effect(
&mut self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
) {
self.analysis.apply_statement_effect(state, stmt, loc);
}
fn reconstruct_before_terminator_effect(
&mut self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
) {
self.analysis.apply_before_terminator_effect(state, term, loc);
}
fn reconstruct_terminator_effect(
&mut self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
) {
self.analysis.apply_terminator_effect(state, term, loc);
}
}