3 use rustc::mir::{Local, Location, Body};
4 use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
5 use rustc_data_structures::indexed_vec::IndexVec;
8 pub struct DefUseAnalysis {
9 info: IndexVec<Local, Info>,
14 pub defs_and_uses: Vec<Use>,
19 pub context: PlaceContext,
20 pub location: Location,
24 pub fn new(body: &Body<'_>) -> DefUseAnalysis {
26 info: IndexVec::from_elem_n(Info::new(), body.local_decls.len()),
30 pub fn analyze(&mut self, body: &Body<'_>) {
33 let mut finder = DefUseFinder {
34 info: mem::take(&mut self.info),
36 finder.visit_body(body);
37 self.info = finder.info
41 for info in &mut self.info {
46 pub fn local_info(&self, local: Local) -> &Info {
50 fn mutate_defs_and_uses<F>(&self, local: Local, body: &mut Body<'_>, mut callback: F)
51 where F: for<'a> FnMut(&'a mut Local,
54 for place_use in &self.info[local].defs_and_uses {
55 MutateUseVisitor::new(local,
57 body).visit_location(body, place_use.location)
61 // FIXME(pcwalton): this should update the def-use chains.
62 pub fn replace_all_defs_and_uses_with(&self,
66 self.mutate_defs_and_uses(local, body, |local, _, _| *local = new_local)
71 info: IndexVec<Local, Info>,
74 impl Visitor<'_> for DefUseFinder {
75 fn visit_local(&mut self,
77 context: PlaceContext,
79 self.info[local].defs_and_uses.push(Use {
89 defs_and_uses: vec![],
94 self.defs_and_uses.clear();
97 pub fn def_count(&self) -> usize {
98 self.defs_and_uses.iter().filter(|place_use| place_use.context.is_mutating_use()).count()
101 pub fn def_count_not_including_drop(&self) -> usize {
102 self.defs_not_including_drop().count()
105 pub fn defs_not_including_drop(
107 ) -> impl Iterator<Item=&Use> {
108 self.defs_and_uses.iter().filter(|place_use| {
109 place_use.context.is_mutating_use() && !place_use.context.is_drop()
113 pub fn use_count(&self) -> usize {
114 self.defs_and_uses.iter().filter(|place_use| {
115 place_use.context.is_nonmutating_use()
120 struct MutateUseVisitor<F> {
125 impl<F> MutateUseVisitor<F> {
126 fn new(query: Local, callback: F, _: &Body<'_>)
127 -> MutateUseVisitor<F>
128 where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) {
136 impl<F> MutVisitor<'_> for MutateUseVisitor<F>
137 where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) {
138 fn visit_local(&mut self,
140 context: PlaceContext,
141 location: Location) {
142 if *local == self.query {
143 (self.callback)(local, context, location)