mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 02:03:53 +00:00
Simplify creation of map
This commit is contained in:
parent
9766ee0b20
commit
8ecb276735
@ -36,7 +36,6 @@ use std::fmt::{Debug, Formatter};
|
|||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::mir::tcx::PlaceTy;
|
|
||||||
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
@ -552,9 +551,10 @@ impl<V: JoinSemiLattice + Clone> JoinSemiLattice for State<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A partial mapping from `Place` to `PlaceIndex`, where some place indices have value indices.
|
/// Partial mapping from [`Place`] to [`PlaceIndex`], where some places also have a [`ValueIndex`].
|
||||||
///
|
///
|
||||||
/// Some additional bookkeeping is done to speed up traversal:
|
/// This data structure essentially maintains a tree of places and their projections. Some
|
||||||
|
/// additional bookkeeping is done, to speed up traversal over this tree:
|
||||||
/// - For iteration, every [`PlaceInfo`] contains an intrusive linked list of its children.
|
/// - For iteration, every [`PlaceInfo`] contains an intrusive linked list of its children.
|
||||||
/// - To directly get the child for a specific projection, there is a `projections` map.
|
/// - To directly get the child for a specific projection, there is a `projections` map.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -578,7 +578,8 @@ impl Map {
|
|||||||
/// Returns a map that only tracks places whose type passes the filter.
|
/// Returns a map that only tracks places whose type passes the filter.
|
||||||
///
|
///
|
||||||
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
|
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
|
||||||
/// chosen is an implementation detail and may not be relied upon.
|
/// chosen is an implementation detail and may not be relied upon (other than that their type
|
||||||
|
/// passes the filter).
|
||||||
#[instrument(skip_all, level = "debug")]
|
#[instrument(skip_all, level = "debug")]
|
||||||
pub fn from_filter<'tcx>(
|
pub fn from_filter<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
@ -599,6 +600,7 @@ impl Map {
|
|||||||
mut filter: impl FnMut(Ty<'tcx>) -> bool,
|
mut filter: impl FnMut(Ty<'tcx>) -> bool,
|
||||||
exclude: &FxHashSet<Place<'tcx>>,
|
exclude: &FxHashSet<Place<'tcx>>,
|
||||||
) {
|
) {
|
||||||
|
// We use this vector as stack, pushing and popping projections.
|
||||||
let mut projection = Vec::new();
|
let mut projection = Vec::new();
|
||||||
for (local, decl) in body.local_decls.iter_enumerated() {
|
for (local, decl) in body.local_decls.iter_enumerated() {
|
||||||
self.register_with_filter_rec(
|
self.register_with_filter_rec(
|
||||||
@ -612,6 +614,9 @@ impl Map {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register fields of the given (local, projection) place.
|
||||||
|
///
|
||||||
|
/// Invariant: The projection must only contain fields.
|
||||||
fn register_with_filter_rec<'tcx>(
|
fn register_with_filter_rec<'tcx>(
|
||||||
&mut self,
|
&mut self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
@ -626,10 +631,19 @@ impl Map {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if filter(ty) {
|
// Note: The framework supports only scalars for now.
|
||||||
// This might fail if `ty` is not scalar.
|
if filter(ty) && ty.is_scalar() {
|
||||||
let _ = self.register_with_ty(local, projection, ty);
|
// We know that the projection only contains trackable elements.
|
||||||
|
let place = self.make_place(local, projection).unwrap();
|
||||||
|
|
||||||
|
// Allocate a value slot if it doesn't have one.
|
||||||
|
if self.places[place].value_index.is_none() {
|
||||||
|
self.places[place].value_index = Some(self.value_count.into());
|
||||||
|
self.value_count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recurse with all fields of this place.
|
||||||
iter_fields(ty, tcx, |variant, field, ty| {
|
iter_fields(ty, tcx, |variant, field, ty| {
|
||||||
if variant.is_some() {
|
if variant.is_some() {
|
||||||
// Downcasts are currently not supported.
|
// Downcasts are currently not supported.
|
||||||
@ -668,59 +682,17 @@ impl Map {
|
|||||||
Ok(index)
|
Ok(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
/// Returns the number of tracked places, i.e., those for which a value can be stored.
|
||||||
fn register<'tcx>(
|
|
||||||
&mut self,
|
|
||||||
local: Local,
|
|
||||||
projection: &[PlaceElem<'tcx>],
|
|
||||||
decls: &impl HasLocalDecls<'tcx>,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
) -> Result<(), ()> {
|
|
||||||
projection
|
|
||||||
.iter()
|
|
||||||
.fold(PlaceTy::from_ty(decls.local_decls()[local].ty), |place_ty, &elem| {
|
|
||||||
place_ty.projection_ty(tcx, elem)
|
|
||||||
});
|
|
||||||
|
|
||||||
let place_ty = Place::ty_from(local, projection, decls, tcx);
|
|
||||||
if place_ty.variant_index.is_some() {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
self.register_with_ty(local, projection, place_ty.ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to track the given place. Fails if type is non-scalar or projection is not trackable.
|
|
||||||
fn register_with_ty<'tcx>(
|
|
||||||
&mut self,
|
|
||||||
local: Local,
|
|
||||||
projection: &[PlaceElem<'tcx>],
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Result<(), ()> {
|
|
||||||
if !ty.is_scalar() {
|
|
||||||
// Currently, only scalar types are allowed, because they are atomic
|
|
||||||
// and therefore do not require invalidation of parent places.
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let place = self.make_place(local, projection)?;
|
|
||||||
|
|
||||||
// Allocate a value slot if it doesn't have one.
|
|
||||||
if self.places[place].value_index.is_none() {
|
|
||||||
self.places[place].value_index = Some(self.value_count.into());
|
|
||||||
self.value_count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tracked_places(&self) -> usize {
|
pub fn tracked_places(&self) -> usize {
|
||||||
self.value_count
|
self.value_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Applies a single projection element, yielding the corresponding child.
|
||||||
pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
|
pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
|
||||||
self.projections.get(&(place, elem)).copied()
|
self.projections.get(&(place, elem)).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Locates the given place, if it exists in the tree.
|
||||||
pub fn find(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
|
pub fn find(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
|
||||||
let mut index = *self.locals.get(place.local)?.as_ref()?;
|
let mut index = *self.locals.get(place.local)?.as_ref()?;
|
||||||
|
|
||||||
@ -736,6 +708,7 @@ impl Map {
|
|||||||
Children::new(self, parent)
|
Children::new(self, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Invoke a function on the given place and all descendants.
|
||||||
pub fn preorder_invoke(&self, root: PlaceIndex, f: &mut impl FnMut(PlaceIndex)) {
|
pub fn preorder_invoke(&self, root: PlaceIndex, f: &mut impl FnMut(PlaceIndex)) {
|
||||||
f(root);
|
f(root);
|
||||||
for child in self.children(root) {
|
for child in self.children(root) {
|
||||||
|
@ -105,7 +105,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
|
|||||||
FlatSet::Top => FlatSet::Top,
|
FlatSet::Top => FlatSet::Top,
|
||||||
FlatSet::Elem(overflow) => {
|
FlatSet::Elem(overflow) => {
|
||||||
if overflow {
|
if overflow {
|
||||||
// Overflow cannot be reliable propagated. See: https://github.com/rust-lang/rust/pull/101168#issuecomment-1288091446
|
// Overflow cannot be reliably propagated. See: https://github.com/rust-lang/rust/pull/101168#issuecomment-1288091446
|
||||||
FlatSet::Top
|
FlatSet::Top
|
||||||
} else {
|
} else {
|
||||||
self.wrap_scalar(Scalar::from_bool(false), self.tcx.types.bool)
|
self.wrap_scalar(Scalar::from_bool(false), self.tcx.types.bool)
|
||||||
|
Loading…
Reference in New Issue
Block a user