Use new dataflow interface for initialization/borrows analyses
This commit is contained in:
parent
702096da17
commit
ce3f37b42b
2 changed files with 220 additions and 133 deletions
|
|
@ -10,7 +10,8 @@ use crate::borrow_check::{
|
|||
places_conflict, BorrowData, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext,
|
||||
ToRegionVid,
|
||||
};
|
||||
use crate::dataflow::{BitDenotation, BottomValue, GenKillSet};
|
||||
use crate::dataflow::generic::{self, GenKill};
|
||||
use crate::dataflow::BottomValue;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
|
@ -172,7 +173,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||
/// That means they went out of a nonlexical scope
|
||||
fn kill_loans_out_of_scope_at_location(
|
||||
&self,
|
||||
trans: &mut GenKillSet<BorrowIndex>,
|
||||
trans: &mut impl GenKill<BorrowIndex>,
|
||||
location: Location,
|
||||
) {
|
||||
// NOTE: The state associated with a given `location`
|
||||
|
|
@ -187,16 +188,21 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||
// region, then setting that gen-bit will override any
|
||||
// potential kill introduced here.
|
||||
if let Some(indices) = self.borrows_out_of_scope_at_location.get(&location) {
|
||||
trans.kill_all(indices);
|
||||
trans.kill_all(indices.iter().copied());
|
||||
}
|
||||
}
|
||||
|
||||
/// Kill any borrows that conflict with `place`.
|
||||
fn kill_borrows_on_place(&self, trans: &mut GenKillSet<BorrowIndex>, place: &Place<'tcx>) {
|
||||
fn kill_borrows_on_place(&self, trans: &mut impl GenKill<BorrowIndex>, place: &Place<'tcx>) {
|
||||
debug!("kill_borrows_on_place: place={:?}", place);
|
||||
|
||||
let other_borrows_of_local =
|
||||
self.borrow_set.local_map.get(&place.local).into_iter().flat_map(|bs| bs.into_iter());
|
||||
let other_borrows_of_local = self
|
||||
.borrow_set
|
||||
.local_map
|
||||
.get(&place.local)
|
||||
.into_iter()
|
||||
.flat_map(|bs| bs.into_iter())
|
||||
.copied();
|
||||
|
||||
// If the borrowed place is a local with no projections, all other borrows of this
|
||||
// local must conflict. This is purely an optimization so we don't have to call
|
||||
|
|
@ -212,7 +218,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||
// pair of array indices are unequal, so that when `places_conflict` returns true, we
|
||||
// will be assured that two places being compared definitely denotes the same sets of
|
||||
// locations.
|
||||
let definitely_conflicting_borrows = other_borrows_of_local.filter(|&&i| {
|
||||
let definitely_conflicting_borrows = other_borrows_of_local.filter(|&i| {
|
||||
places_conflict(
|
||||
self.tcx,
|
||||
self.body,
|
||||
|
|
@ -226,36 +232,41 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
|
||||
impl<'tcx> generic::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
||||
type Idx = BorrowIndex;
|
||||
fn name() -> &'static str {
|
||||
"borrows"
|
||||
}
|
||||
fn bits_per_block(&self) -> usize {
|
||||
|
||||
const NAME: &'static str = "borrows";
|
||||
|
||||
fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
|
||||
self.borrow_set.borrows.len() * 2
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, _entry_set: &mut BitSet<Self::Idx>) {
|
||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut BitSet<Self::Idx>) {
|
||||
// no borrows of code region_scopes have been taken prior to
|
||||
// function execution, so this method has no effect.
|
||||
}
|
||||
|
||||
fn before_statement_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
debug!("Borrows::before_statement_effect trans: {:?} location: {:?}", trans, location);
|
||||
fn pretty_print_idx(&self, w: &mut impl std::io::Write, idx: Self::Idx) -> std::io::Result<()> {
|
||||
write!(w, "{:?}", self.location(idx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> generic::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
fn before_statement_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
self.kill_loans_out_of_scope_at_location(trans, location);
|
||||
}
|
||||
|
||||
fn statement_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
debug!("Borrows::statement_effect: trans={:?} location={:?}", trans, location);
|
||||
|
||||
let block = &self.body.basic_blocks().get(location.block).unwrap_or_else(|| {
|
||||
panic!("could not find block at location {:?}", location);
|
||||
});
|
||||
let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| {
|
||||
panic!("could not find statement at location {:?}");
|
||||
});
|
||||
|
||||
debug!("Borrows::statement_effect: stmt={:?}", stmt);
|
||||
fn statement_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
match stmt.kind {
|
||||
mir::StatementKind::Assign(box (ref lhs, ref rhs)) => {
|
||||
if let mir::Rvalue::Ref(_, _, ref place) = *rhs {
|
||||
|
|
@ -301,18 +312,29 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn before_terminator_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
debug!("Borrows::before_terminator_effect: trans={:?} location={:?}", trans, location);
|
||||
fn before_terminator_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
self.kill_loans_out_of_scope_at_location(trans, location);
|
||||
}
|
||||
|
||||
fn terminator_effect(&self, _: &mut GenKillSet<Self::Idx>, _: Location) {}
|
||||
|
||||
fn propagate_call_return(
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
_in_out: &mut BitSet<BorrowIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
_: &mut impl GenKill<Self::Idx>,
|
||||
_: &mir::Terminator<'tcx>,
|
||||
_: Location,
|
||||
) {
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: mir::BasicBlock,
|
||||
_func: &mir::Operand<'tcx>,
|
||||
_args: &[mir::Operand<'tcx>],
|
||||
_dest_place: &mir::Place<'tcx>,
|
||||
) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ use super::MoveDataParamEnv;
|
|||
|
||||
use crate::util::elaborate_drops::DropFlagState;
|
||||
|
||||
use super::generic::{AnalysisDomain, GenKill, GenKillAnalysis};
|
||||
use super::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex};
|
||||
use super::{BitDenotation, BottomValue, GenKillSet};
|
||||
use super::{BottomValue, GenKillSet};
|
||||
|
||||
use super::drop_flag_effects_for_function_entry;
|
||||
use super::drop_flag_effects_for_location;
|
||||
|
|
@ -216,6 +217,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
|||
/// }
|
||||
/// ```
|
||||
pub struct EverInitializedPlaces<'a, 'tcx> {
|
||||
#[allow(dead_code)]
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
mdpe: &'a MoveDataParamEnv<'tcx>,
|
||||
|
|
@ -235,7 +237,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
||||
fn update_bits(
|
||||
trans: &mut GenKillSet<MovePathIndex>,
|
||||
trans: &mut impl GenKill<MovePathIndex>,
|
||||
path: MovePathIndex,
|
||||
state: DropFlagState,
|
||||
) {
|
||||
|
|
@ -248,7 +250,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
|
||||
fn update_bits(
|
||||
trans: &mut GenKillSet<MovePathIndex>,
|
||||
trans: &mut impl GenKill<MovePathIndex>,
|
||||
path: MovePathIndex,
|
||||
state: DropFlagState,
|
||||
) {
|
||||
|
|
@ -261,7 +263,7 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||
fn update_bits(
|
||||
trans: &mut GenKillSet<MovePathIndex>,
|
||||
trans: &mut impl GenKill<MovePathIndex>,
|
||||
path: MovePathIndex,
|
||||
state: DropFlagState,
|
||||
) {
|
||||
|
|
@ -272,39 +274,56 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BitDenotation<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
|
||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
type Idx = MovePathIndex;
|
||||
fn name() -> &'static str {
|
||||
"maybe_init"
|
||||
}
|
||||
fn bits_per_block(&self) -> usize {
|
||||
|
||||
const NAME: &'static str = "maybe_init";
|
||||
|
||||
fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
|
||||
self.move_data().move_paths.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
|
||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
|
||||
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
entry_set.insert(path);
|
||||
state.insert(path);
|
||||
});
|
||||
}
|
||||
|
||||
fn statement_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
fn pretty_print_idx(&self, w: &mut impl std::io::Write, mpi: Self::Idx) -> std::io::Result<()> {
|
||||
write!(w, "{}", self.move_data().move_paths[mpi])
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn propagate_call_return(
|
||||
impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
fn statement_effect(
|
||||
&self,
|
||||
in_out: &mut BitSet<MovePathIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: mir::BasicBlock,
|
||||
_func: &mir::Operand<'tcx>,
|
||||
_args: &[mir::Operand<'tcx>],
|
||||
dest_place: &mir::Place<'tcx>,
|
||||
) {
|
||||
// when a call returns successfully, that means we need to set
|
||||
|
|
@ -315,50 +334,67 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
|
|||
self.move_data(),
|
||||
self.move_data().rev_lookup.find(dest_place.as_ref()),
|
||||
|mpi| {
|
||||
in_out.insert(mpi);
|
||||
trans.gen(mpi);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BitDenotation<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
|
||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
type Idx = MovePathIndex;
|
||||
fn name() -> &'static str {
|
||||
"maybe_uninit"
|
||||
}
|
||||
fn bits_per_block(&self) -> usize {
|
||||
|
||||
const NAME: &'static str = "maybe_uninit";
|
||||
|
||||
fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
|
||||
self.move_data().move_paths.len()
|
||||
}
|
||||
|
||||
// sets on_entry bits for Arg places
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
|
||||
fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
|
||||
// set all bits to 1 (uninit) before gathering counterevidence
|
||||
assert!(self.bits_per_block() == entry_set.domain_size());
|
||||
entry_set.insert_all();
|
||||
assert!(self.bits_per_block(body) == state.domain_size());
|
||||
state.insert_all();
|
||||
|
||||
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
entry_set.remove(path);
|
||||
state.remove(path);
|
||||
});
|
||||
}
|
||||
|
||||
fn statement_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
fn pretty_print_idx(&self, w: &mut impl std::io::Write, mpi: Self::Idx) -> std::io::Result<()> {
|
||||
write!(w, "{}", self.move_data().move_paths[mpi])
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn propagate_call_return(
|
||||
impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
fn statement_effect(
|
||||
&self,
|
||||
in_out: &mut BitSet<MovePathIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: mir::BasicBlock,
|
||||
_func: &mir::Operand<'tcx>,
|
||||
_args: &[mir::Operand<'tcx>],
|
||||
dest_place: &mir::Place<'tcx>,
|
||||
) {
|
||||
// when a call returns successfully, that means we need to set
|
||||
|
|
@ -369,48 +405,65 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
|
|||
self.move_data(),
|
||||
self.move_data().rev_lookup.find(dest_place.as_ref()),
|
||||
|mpi| {
|
||||
in_out.remove(mpi);
|
||||
trans.kill(mpi);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BitDenotation<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||
impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||
type Idx = MovePathIndex;
|
||||
fn name() -> &'static str {
|
||||
"definite_init"
|
||||
}
|
||||
fn bits_per_block(&self) -> usize {
|
||||
|
||||
const NAME: &'static str = "definite_init";
|
||||
|
||||
fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
|
||||
self.move_data().move_paths.len()
|
||||
}
|
||||
|
||||
// sets on_entry bits for Arg places
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
|
||||
entry_set.clear();
|
||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
|
||||
state.clear();
|
||||
|
||||
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
entry_set.insert(path);
|
||||
state.insert(path);
|
||||
});
|
||||
}
|
||||
|
||||
fn statement_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
fn pretty_print_idx(&self, w: &mut impl std::io::Write, mpi: Self::Idx) -> std::io::Result<()> {
|
||||
write!(w, "{}", self.move_data().move_paths[mpi])
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn propagate_call_return(
|
||||
impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
||||
fn statement_effect(
|
||||
&self,
|
||||
in_out: &mut BitSet<MovePathIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: mir::BasicBlock,
|
||||
_func: &mir::Operand<'tcx>,
|
||||
_args: &[mir::Operand<'tcx>],
|
||||
dest_place: &mir::Place<'tcx>,
|
||||
) {
|
||||
// when a call returns successfully, that means we need to set
|
||||
|
|
@ -421,30 +474,36 @@ impl<'a, 'tcx> BitDenotation<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
|||
self.move_data(),
|
||||
self.move_data().rev_lookup.find(dest_place.as_ref()),
|
||||
|mpi| {
|
||||
in_out.insert(mpi);
|
||||
trans.gen(mpi);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
|
||||
impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
||||
type Idx = InitIndex;
|
||||
fn name() -> &'static str {
|
||||
"ever_init"
|
||||
}
|
||||
fn bits_per_block(&self) -> usize {
|
||||
|
||||
const NAME: &'static str = "ever_init";
|
||||
|
||||
fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
|
||||
self.move_data().inits.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<InitIndex>) {
|
||||
for arg_init in 0..self.body.arg_count {
|
||||
entry_set.insert(InitIndex::new(arg_init));
|
||||
fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
|
||||
for arg_init in 0..body.arg_count {
|
||||
state.insert(InitIndex::new(arg_init));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn statement_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
let (_, body, move_data) = (self.tcx, self.body, self.move_data());
|
||||
let stmt = &body[location.block].statements[location.statement_index];
|
||||
impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
||||
fn statement_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
let move_data = self.move_data();
|
||||
let init_path_map = &move_data.init_path_map;
|
||||
let init_loc_map = &move_data.init_loc_map;
|
||||
let rev_lookup = &move_data.rev_lookup;
|
||||
|
|
@ -453,7 +512,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
|
|||
"statement {:?} at loc {:?} initializes move_indexes {:?}",
|
||||
stmt, location, &init_loc_map[location]
|
||||
);
|
||||
trans.gen_all(&init_loc_map[location]);
|
||||
trans.gen_all(init_loc_map[location].iter().copied());
|
||||
|
||||
match stmt.kind {
|
||||
mir::StatementKind::StorageDead(local) => {
|
||||
|
|
@ -464,13 +523,18 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
|
|||
"stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
|
||||
stmt, location, &init_path_map[move_path_index]
|
||||
);
|
||||
trans.kill_all(&init_path_map[move_path_index]);
|
||||
trans.kill_all(init_path_map[move_path_index].iter().copied());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(&self, trans: &mut GenKillSet<Self::Idx>, location: Location) {
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
let (body, move_data) = (self.body, self.move_data());
|
||||
let term = body[location.block].terminator();
|
||||
let init_loc_map = &move_data.init_loc_map;
|
||||
|
|
@ -479,28 +543,29 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
|
|||
term, location, &init_loc_map[location]
|
||||
);
|
||||
trans.gen_all(
|
||||
init_loc_map[location].iter().filter(|init_index| {
|
||||
move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
|
||||
}),
|
||||
init_loc_map[location]
|
||||
.iter()
|
||||
.filter(|init_index| {
|
||||
move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
|
||||
})
|
||||
.copied(),
|
||||
);
|
||||
}
|
||||
|
||||
fn propagate_call_return(
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
in_out: &mut BitSet<InitIndex>,
|
||||
call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
block: mir::BasicBlock,
|
||||
_func: &mir::Operand<'tcx>,
|
||||
_args: &[mir::Operand<'tcx>],
|
||||
_dest_place: &mir::Place<'tcx>,
|
||||
) {
|
||||
let move_data = self.move_data();
|
||||
let bits_per_block = self.bits_per_block();
|
||||
let init_loc_map = &move_data.init_loc_map;
|
||||
|
||||
let call_loc =
|
||||
Location { block: call_bb, statement_index: self.body[call_bb].statements.len() };
|
||||
let call_loc = self.body.terminator_loc(block);
|
||||
for init_index in &init_loc_map[call_loc] {
|
||||
assert!(init_index.index() < bits_per_block);
|
||||
in_out.insert(*init_index);
|
||||
trans.gen(*init_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue