1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use flowistry::{
  infoflow::mutation::{ModularMutationVisitor, Mutation},
  mir::placeinfo::PlaceInfo,
};
use indexical::impls::RustcIndexMatrix;
use rustc_middle::mir::{visit::Visitor, Body, Mutability, Place};
use rustc_utils::mir::location_or_arg::LocationOrArg;

pub struct DirectInfluence<'a, 'tcx> {
  place_info: &'a PlaceInfo<'a, 'tcx>,
  influence: RustcIndexMatrix<Place<'tcx>, LocationOrArg>,
}

impl<'a, 'tcx> DirectInfluence<'a, 'tcx> {
  pub fn build(body: &Body<'tcx>, place_info: &'a PlaceInfo<'a, 'tcx>) -> Self {
    let mut influence = RustcIndexMatrix::new(place_info.location_domain());

    ModularMutationVisitor::new(place_info, |location, mutations| {
      let mut add = |place: Place<'tcx>, mutability: Mutability| {
        for alias in place_info.reachable_values(place, mutability) {
          influence.insert(*alias, location);
        }
      };

      for Mutation {
        mutated, inputs, ..
      } in mutations
      {
        for input in inputs {
          add(input, Mutability::Not);
        }

        add(mutated, Mutability::Mut);
      }
    })
    .visit_body(body);

    DirectInfluence {
      place_info,
      influence,
    }
  }

  pub fn lookup(&self, target: Place<'tcx>) -> Vec<LocationOrArg> {
    let aliases = self.place_info.reachable_values(target, Mutability::Not);
    aliases
      .iter()
      .flat_map(|target_alias| {
        self
          .influence
          .row_set(target_alias)
          .iter()
          .copied()
          .collect::<Vec<_>>()
      })
      .collect::<Vec<_>>()
  }
}