refactor access fact generation
- use consistent names - inline single use functions - dedupe and simplify some paths - fix fact generation timer activity: it was missing the walk and extraction process
This commit is contained in:
parent
b0e04d5a0c
commit
585c71fd3e
3 changed files with 67 additions and 80 deletions
|
@ -45,7 +45,7 @@ pub(super) fn generate<'a, 'tcx>(
|
||||||
let (relevant_live_locals, boring_locals) =
|
let (relevant_live_locals, boring_locals) =
|
||||||
compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
|
compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
|
||||||
|
|
||||||
polonius::populate_access_facts(typeck, body, move_data);
|
polonius::emit_access_facts(typeck, body, move_data);
|
||||||
|
|
||||||
trace::trace(
|
trace::trace(
|
||||||
typeck,
|
typeck,
|
||||||
|
|
|
@ -11,88 +11,19 @@ use crate::location::{LocationIndex, LocationTable};
|
||||||
type VarPointRelation = Vec<(Local, LocationIndex)>;
|
type VarPointRelation = Vec<(Local, LocationIndex)>;
|
||||||
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
|
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
|
||||||
|
|
||||||
struct UseFactsExtractor<'a, 'tcx> {
|
/// Emit polonius facts for variable defs, uses, drops, and path accesses.
|
||||||
var_defined_at: &'a mut VarPointRelation,
|
pub(super) fn emit_access_facts<'a, 'tcx>(
|
||||||
var_used_at: &'a mut VarPointRelation,
|
|
||||||
location_table: &'a LocationTable,
|
|
||||||
var_dropped_at: &'a mut VarPointRelation,
|
|
||||||
move_data: &'a MoveData<'tcx>,
|
|
||||||
path_accessed_at_base: &'a mut PathPointRelation,
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Visitor to walk through the MIR and extract point-wise facts
|
|
||||||
impl<'tcx> UseFactsExtractor<'_, 'tcx> {
|
|
||||||
fn location_to_index(&self, location: Location) -> LocationIndex {
|
|
||||||
self.location_table.mid_index(location)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_def(&mut self, local: Local, location: Location) {
|
|
||||||
debug!("UseFactsExtractor::insert_def()");
|
|
||||||
self.var_defined_at.push((local, self.location_to_index(location)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_use(&mut self, local: Local, location: Location) {
|
|
||||||
debug!("UseFactsExtractor::insert_use()");
|
|
||||||
self.var_used_at.push((local, self.location_to_index(location)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_drop_use(&mut self, local: Local, location: Location) {
|
|
||||||
debug!("UseFactsExtractor::insert_drop_use()");
|
|
||||||
self.var_dropped_at.push((local, self.location_to_index(location)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
|
|
||||||
debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location);
|
|
||||||
self.path_accessed_at_base.push((path, self.location_to_index(location)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn place_to_mpi(&self, place: &Place<'tcx>) -> Option<MovePathIndex> {
|
|
||||||
match self.move_data.rev_lookup.find(place.as_ref()) {
|
|
||||||
LookupResult::Exact(mpi) => Some(mpi),
|
|
||||||
LookupResult::Parent(mmpi) => mmpi,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> {
|
|
||||||
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
|
|
||||||
match def_use::categorize(context) {
|
|
||||||
Some(DefUse::Def) => self.insert_def(local, location),
|
|
||||||
Some(DefUse::Use) => self.insert_use(local, location),
|
|
||||||
Some(DefUse::Drop) => self.insert_drop_use(local, location),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
|
||||||
self.super_place(place, context, location);
|
|
||||||
match context {
|
|
||||||
PlaceContext::NonMutatingUse(_) => {
|
|
||||||
if let Some(mpi) = self.place_to_mpi(place) {
|
|
||||||
self.insert_path_access(mpi, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
|
|
||||||
if let Some(mpi) = self.place_to_mpi(place) {
|
|
||||||
self.insert_path_access(mpi, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn populate_access_facts<'a, 'tcx>(
|
|
||||||
typeck: &mut TypeChecker<'a, 'tcx>,
|
typeck: &mut TypeChecker<'a, 'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
move_data: &MoveData<'tcx>,
|
move_data: &MoveData<'tcx>,
|
||||||
) {
|
) {
|
||||||
if let Some(facts) = typeck.all_facts.as_mut() {
|
if let Some(facts) = typeck.all_facts.as_mut() {
|
||||||
debug!("populate_access_facts()");
|
debug!("emit_access_facts()");
|
||||||
|
|
||||||
|
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||||
let location_table = typeck.location_table;
|
let location_table = typeck.location_table;
|
||||||
|
|
||||||
let mut extractor = UseFactsExtractor {
|
let mut extractor = AccessFactsExtractor {
|
||||||
var_defined_at: &mut facts.var_defined_at,
|
var_defined_at: &mut facts.var_defined_at,
|
||||||
var_used_at: &mut facts.var_used_at,
|
var_used_at: &mut facts.var_used_at,
|
||||||
var_dropped_at: &mut facts.var_dropped_at,
|
var_dropped_at: &mut facts.var_dropped_at,
|
||||||
|
@ -107,7 +38,6 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
|
||||||
"add use_of_var_derefs_origin facts - local={:?}, type={:?}",
|
"add use_of_var_derefs_origin facts - local={:?}, type={:?}",
|
||||||
local, local_decl.ty
|
local, local_decl.ty
|
||||||
);
|
);
|
||||||
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
|
||||||
let universal_regions = &typeck.universal_regions;
|
let universal_regions = &typeck.universal_regions;
|
||||||
typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
|
typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
|
||||||
let region_vid = universal_regions.to_region_vid(region);
|
let region_vid = universal_regions.to_region_vid(region);
|
||||||
|
@ -119,12 +49,12 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
|
||||||
|
|
||||||
/// For every potentially drop()-touched region `region` in `local`'s type
|
/// For every potentially drop()-touched region `region` in `local`'s type
|
||||||
/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
|
/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
|
||||||
pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
|
pub(super) fn emit_drop_facts<'tcx>(
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||||
local: Local,
|
local: Local,
|
||||||
kind: &GenericArg<'tcx>,
|
kind: &GenericArg<'tcx>,
|
||||||
) {
|
) {
|
||||||
debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind);
|
debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind);
|
||||||
if let Some(facts) = typeck.all_facts.as_mut() {
|
if let Some(facts) = typeck.all_facts.as_mut() {
|
||||||
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||||
let universal_regions = &typeck.universal_regions;
|
let universal_regions = &typeck.universal_regions;
|
||||||
|
@ -134,3 +64,60 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// MIR visitor extracting point-wise facts about accesses.
|
||||||
|
struct AccessFactsExtractor<'a, 'tcx> {
|
||||||
|
var_defined_at: &'a mut VarPointRelation,
|
||||||
|
var_used_at: &'a mut VarPointRelation,
|
||||||
|
location_table: &'a LocationTable,
|
||||||
|
var_dropped_at: &'a mut VarPointRelation,
|
||||||
|
move_data: &'a MoveData<'tcx>,
|
||||||
|
path_accessed_at_base: &'a mut PathPointRelation,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
|
||||||
|
fn location_to_index(&self, location: Location) -> LocationIndex {
|
||||||
|
self.location_table.mid_index(location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
|
||||||
|
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
|
||||||
|
match def_use::categorize(context) {
|
||||||
|
Some(DefUse::Def) => {
|
||||||
|
debug!("AccessFactsExtractor - emit def");
|
||||||
|
self.var_defined_at.push((local, self.location_to_index(location)));
|
||||||
|
}
|
||||||
|
Some(DefUse::Use) => {
|
||||||
|
debug!("AccessFactsExtractor - emit use");
|
||||||
|
self.var_used_at.push((local, self.location_to_index(location)));
|
||||||
|
}
|
||||||
|
Some(DefUse::Drop) => {
|
||||||
|
debug!("AccessFactsExtractor - emit drop");
|
||||||
|
self.var_dropped_at.push((local, self.location_to_index(location)));
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
||||||
|
self.super_place(place, context, location);
|
||||||
|
|
||||||
|
match context {
|
||||||
|
PlaceContext::NonMutatingUse(_)
|
||||||
|
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
|
||||||
|
let path = match self.move_data.rev_lookup.find(place.as_ref()) {
|
||||||
|
LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
|
||||||
|
_ => {
|
||||||
|
// There's no path access to emit.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
|
||||||
|
self.path_accessed_at_base.push((path, self.location_to_index(location)));
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -590,7 +590,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||||
// the destructor and must be live at this point.
|
// the destructor and must be live at this point.
|
||||||
for &kind in &drop_data.dropck_result.kinds {
|
for &kind in &drop_data.dropck_result.kinds {
|
||||||
Self::make_all_regions_live(self.elements, self.typeck, kind, live_at);
|
Self::make_all_regions_live(self.elements, self.typeck, kind, live_at);
|
||||||
polonius::add_drop_of_var_derefs_origin(self.typeck, dropped_local, &kind);
|
polonius::emit_drop_facts(self.typeck, dropped_local, &kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue