Skip to content

Commit dc063c5

Browse files
committed
Extend value_analysis API.
1 parent 72ff82c commit dc063c5

File tree

1 file changed

+50
-20
lines changed

1 file changed

+50
-20
lines changed

compiler/rustc_mir_dataflow/src/value_analysis.rs

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ rustc_index::newtype_index!(
2424

2525
rustc_index::newtype_index!(
2626
/// This index uniquely identifies a tracked place and therefore a slot in [`State`].
27-
///
28-
/// It is an implementation detail of this module.
29-
struct ValueIndex {}
27+
pub struct ValueIndex {}
3028
);
3129

3230
/// See [`State`].
@@ -211,22 +209,9 @@ impl<V: Clone + HasBottom> State<V> {
211209
/// The target place must have been flooded before calling this method.
212210
pub fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map<'_>) {
213211
let State::Reachable(values) = self else { return };
214-
215-
// If both places are tracked, we copy the value to the target.
216-
// If the target is tracked, but the source is not, we do nothing, as invalidation has
217-
// already been performed.
218-
if let Some(target_value) = map.places[target].value_index
219-
&& let Some(source_value) = map.places[source].value_index
220-
{
221-
values.insert(target_value, values.get(source_value).clone());
222-
}
223-
for target_child in map.children(target) {
224-
// Try to find corresponding child and recurse. Reasoning is similar as above.
225-
let projection = map.places[target_child].proj_elem.unwrap();
226-
if let Some(source_child) = map.projections.get(&(source, projection)) {
227-
self.insert_place_idx(target_child, *source_child, map);
228-
}
229-
}
212+
map.for_each_value_pair(target, source, &mut |target, source| {
213+
values.insert(target, values.get(source).clone());
214+
});
230215
}
231216

232217
/// Helper method to interpret `target = result`.
@@ -677,6 +662,26 @@ impl<'tcx> Map<'tcx> {
677662
self.find_extra(place, [TrackElem::DerefLen])
678663
}
679664

665+
/// Locates the value corresponding to the given place.
666+
pub fn value(&self, place: PlaceIndex) -> Option<ValueIndex> {
667+
self.places[place].value_index
668+
}
669+
670+
/// Locates the value corresponding to the given place.
671+
pub fn find_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
672+
self.value(self.find(place)?)
673+
}
674+
675+
/// Locates the value corresponding to the given discriminant.
676+
pub fn find_discr_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
677+
self.value(self.find_discr(place)?)
678+
}
679+
680+
/// Locates the value corresponding to the given length.
681+
pub fn find_len_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
682+
self.value(self.find_len(place)?)
683+
}
684+
680685
/// Iterate over all direct children.
681686
fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> {
682687
Children::new(self, parent)
@@ -689,7 +694,7 @@ impl<'tcx> Map<'tcx> {
689694
///
690695
/// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
691696
/// as such.
692-
fn for_each_aliasing_place(
697+
pub fn for_each_aliasing_place(
693698
&self,
694699
place: PlaceRef<'_>,
695700
tail_elem: Option<TrackElem>,
@@ -778,6 +783,31 @@ impl<'tcx> Map<'tcx> {
778783
}
779784
}
780785
}
786+
787+
/// Recursively iterates on each value contained in `target`, paired with matching projection
788+
/// inside `source`.
789+
pub fn for_each_value_pair(
790+
&self,
791+
target: PlaceIndex,
792+
source: PlaceIndex,
793+
f: &mut impl FnMut(ValueIndex, ValueIndex),
794+
) {
795+
// If both places are tracked, we copy the value to the target.
796+
// If the target is tracked, but the source is not, we do nothing, as invalidation has
797+
// already been performed.
798+
if let Some(target_value) = self.places[target].value_index
799+
&& let Some(source_value) = self.places[source].value_index
800+
{
801+
f(target_value, source_value)
802+
}
803+
for target_child in self.children(target) {
804+
// Try to find corresponding child and recurse. Reasoning is similar as above.
805+
let projection = self.places[target_child].proj_elem.unwrap();
806+
if let Some(source_child) = self.projections.get(&(source, projection)) {
807+
self.for_each_value_pair(target_child, *source_child, f);
808+
}
809+
}
810+
}
781811
}
782812

783813
/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].

0 commit comments

Comments
 (0)