mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Extend value_analysis API.
This commit is contained in:
@@ -24,9 +24,7 @@ pub struct PlaceIndex {}
|
||||
|
||||
rustc_index::newtype_index!(
|
||||
/// This index uniquely identifies a tracked place and therefore a slot in [`State`].
|
||||
///
|
||||
/// It is an implementation detail of this module.
|
||||
struct ValueIndex {}
|
||||
pub struct ValueIndex {}
|
||||
);
|
||||
|
||||
/// See [`State`].
|
||||
@@ -211,22 +209,9 @@ pub fn insert_value_idx(&mut self, target: PlaceIndex, value: V, map: &Map<'_>)
|
||||
/// The target place must have been flooded before calling this method.
|
||||
pub fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map<'_>) {
|
||||
let State::Reachable(values) = self else { return };
|
||||
|
||||
// If both places are tracked, we copy the value to the target.
|
||||
// If the target is tracked, but the source is not, we do nothing, as invalidation has
|
||||
// already been performed.
|
||||
if let Some(target_value) = map.places[target].value_index
|
||||
&& let Some(source_value) = map.places[source].value_index
|
||||
{
|
||||
values.insert(target_value, values.get(source_value).clone());
|
||||
}
|
||||
for target_child in map.children(target) {
|
||||
// Try to find corresponding child and recurse. Reasoning is similar as above.
|
||||
let projection = map.places[target_child].proj_elem.unwrap();
|
||||
if let Some(source_child) = map.projections.get(&(source, projection)) {
|
||||
self.insert_place_idx(target_child, *source_child, map);
|
||||
}
|
||||
}
|
||||
map.for_each_value_pair(target, source, &mut |target, source| {
|
||||
values.insert(target, values.get(source).clone());
|
||||
});
|
||||
}
|
||||
|
||||
/// Helper method to interpret `target = result`.
|
||||
@@ -677,6 +662,26 @@ pub fn find_len(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
|
||||
self.find_extra(place, [TrackElem::DerefLen])
|
||||
}
|
||||
|
||||
/// Locates the value corresponding to the given place.
|
||||
pub fn value(&self, place: PlaceIndex) -> Option<ValueIndex> {
|
||||
self.places[place].value_index
|
||||
}
|
||||
|
||||
/// Locates the value corresponding to the given place.
|
||||
pub fn find_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
|
||||
self.value(self.find(place)?)
|
||||
}
|
||||
|
||||
/// Locates the value corresponding to the given discriminant.
|
||||
pub fn find_discr_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
|
||||
self.value(self.find_discr(place)?)
|
||||
}
|
||||
|
||||
/// Locates the value corresponding to the given length.
|
||||
pub fn find_len_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
|
||||
self.value(self.find_len(place)?)
|
||||
}
|
||||
|
||||
/// Iterate over all direct children.
|
||||
fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> {
|
||||
Children::new(self, parent)
|
||||
@@ -689,7 +694,7 @@ fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> {
|
||||
///
|
||||
/// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
|
||||
/// as such.
|
||||
fn for_each_aliasing_place(
|
||||
pub fn for_each_aliasing_place(
|
||||
&self,
|
||||
place: PlaceRef<'_>,
|
||||
tail_elem: Option<TrackElem>,
|
||||
@@ -778,6 +783,31 @@ pub fn for_each_projection_value<O>(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursively iterates on each value contained in `target`, paired with matching projection
|
||||
/// inside `source`.
|
||||
pub fn for_each_value_pair(
|
||||
&self,
|
||||
target: PlaceIndex,
|
||||
source: PlaceIndex,
|
||||
f: &mut impl FnMut(ValueIndex, ValueIndex),
|
||||
) {
|
||||
// If both places are tracked, we copy the value to the target.
|
||||
// If the target is tracked, but the source is not, we do nothing, as invalidation has
|
||||
// already been performed.
|
||||
if let Some(target_value) = self.places[target].value_index
|
||||
&& let Some(source_value) = self.places[source].value_index
|
||||
{
|
||||
f(target_value, source_value)
|
||||
}
|
||||
for target_child in self.children(target) {
|
||||
// Try to find corresponding child and recurse. Reasoning is similar as above.
|
||||
let projection = self.places[target_child].proj_elem.unwrap();
|
||||
if let Some(source_child) = self.projections.get(&(source, projection)) {
|
||||
self.for_each_value_pair(target_child, *source_child, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].
|
||||
|
||||
Reference in New Issue
Block a user