]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/util/def_use.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / librustc_mir / util / def_use.rs
CommitLineData
9e0c209e
SL
1//! Def-use analysis.
2
ea8adc8c 3use rustc::mir::{Local, Location, Mir};
ff7c6d11 4use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
c30ab7b3 5use rustc_data_structures::indexed_vec::IndexVec;
9e0c209e
SL
6use std::marker::PhantomData;
7use std::mem;
abe05a73
XL
8use std::slice;
9use std::iter;
9e0c209e
SL
10
11pub struct DefUseAnalysis<'tcx> {
12 info: IndexVec<Local, Info<'tcx>>,
9e0c209e
SL
13}
14
15#[derive(Clone)]
16pub struct Info<'tcx> {
17 pub defs_and_uses: Vec<Use<'tcx>>,
18}
19
20#[derive(Clone)]
21pub struct Use<'tcx> {
ff7c6d11 22 pub context: PlaceContext<'tcx>,
9e0c209e
SL
23 pub location: Location,
24}
25
26impl<'tcx> DefUseAnalysis<'tcx> {
27 pub fn new(mir: &Mir<'tcx>) -> DefUseAnalysis<'tcx> {
28 DefUseAnalysis {
c30ab7b3 29 info: IndexVec::from_elem_n(Info::new(), mir.local_decls.len()),
9e0c209e
SL
30 }
31 }
32
33 pub fn analyze(&mut self, mir: &Mir<'tcx>) {
abe05a73
XL
34 self.clear();
35
9e0c209e
SL
36 let mut finder = DefUseFinder {
37 info: mem::replace(&mut self.info, IndexVec::new()),
9e0c209e
SL
38 };
39 finder.visit_mir(mir);
40 self.info = finder.info
41 }
42
abe05a73
XL
43 fn clear(&mut self) {
44 for info in &mut self.info {
45 info.clear();
46 }
47 }
48
9e0c209e
SL
49 pub fn local_info(&self, local: Local) -> &Info<'tcx> {
50 &self.info[local]
51 }
52
9e0c209e 53 fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F)
ea8adc8c 54 where F: for<'a> FnMut(&'a mut Local,
ff7c6d11 55 PlaceContext<'tcx>,
9e0c209e 56 Location) {
ff7c6d11 57 for place_use in &self.info[local].defs_and_uses {
9e0c209e
SL
58 MutateUseVisitor::new(local,
59 &mut callback,
ff7c6d11 60 mir).visit_location(mir, place_use.location)
9e0c209e
SL
61 }
62 }
63
9fa01778 64 // FIXME(pcwalton): this should update the def-use chains.
9e0c209e
SL
65 pub fn replace_all_defs_and_uses_with(&self,
66 local: Local,
67 mir: &mut Mir<'tcx>,
ea8adc8c
XL
68 new_local: Local) {
69 self.mutate_defs_and_uses(local, mir, |local, _, _| *local = new_local)
9e0c209e
SL
70 }
71}
72
73struct DefUseFinder<'tcx> {
74 info: IndexVec<Local, Info<'tcx>>,
9e0c209e
SL
75}
76
9e0c209e 77impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> {
ea8adc8c
XL
78 fn visit_local(&mut self,
79 &local: &Local,
ff7c6d11 80 context: PlaceContext<'tcx>,
ea8adc8c
XL
81 location: Location) {
82 self.info[local].defs_and_uses.push(Use {
83 context,
84 location,
85 });
9e0c209e
SL
86 }
87}
88
89impl<'tcx> Info<'tcx> {
90 fn new() -> Info<'tcx> {
91 Info {
92 defs_and_uses: vec![],
93 }
94 }
95
abe05a73
XL
96 fn clear(&mut self) {
97 self.defs_and_uses.clear();
98 }
99
9e0c209e 100 pub fn def_count(&self) -> usize {
ff7c6d11 101 self.defs_and_uses.iter().filter(|place_use| place_use.context.is_mutating_use()).count()
9e0c209e
SL
102 }
103
104 pub fn def_count_not_including_drop(&self) -> usize {
abe05a73
XL
105 self.defs_not_including_drop().count()
106 }
107
108 pub fn defs_not_including_drop(
109 &self,
9fa01778 110 ) -> iter::Filter<slice::Iter<'_, Use<'tcx>>, fn(&&Use<'tcx>) -> bool> {
ff7c6d11
XL
111 self.defs_and_uses.iter().filter(|place_use| {
112 place_use.context.is_mutating_use() && !place_use.context.is_drop()
abe05a73 113 })
9e0c209e
SL
114 }
115
116 pub fn use_count(&self) -> usize {
ff7c6d11
XL
117 self.defs_and_uses.iter().filter(|place_use| {
118 place_use.context.is_nonmutating_use()
9e0c209e
SL
119 }).count()
120 }
121}
122
123struct MutateUseVisitor<'tcx, F> {
124 query: Local,
125 callback: F,
9e0c209e
SL
126 phantom: PhantomData<&'tcx ()>,
127}
128
129impl<'tcx, F> MutateUseVisitor<'tcx, F> {
c30ab7b3 130 fn new(query: Local, callback: F, _: &Mir<'tcx>)
9e0c209e 131 -> MutateUseVisitor<'tcx, F>
ff7c6d11 132 where F: for<'a> FnMut(&'a mut Local, PlaceContext<'tcx>, Location) {
9e0c209e 133 MutateUseVisitor {
3b2f2976
XL
134 query,
135 callback,
9e0c209e
SL
136 phantom: PhantomData,
137 }
138 }
139}
140
141impl<'tcx, F> MutVisitor<'tcx> for MutateUseVisitor<'tcx, F>
ff7c6d11 142 where F: for<'a> FnMut(&'a mut Local, PlaceContext<'tcx>, Location) {
ea8adc8c
XL
143 fn visit_local(&mut self,
144 local: &mut Local,
ff7c6d11 145 context: PlaceContext<'tcx>,
9e0c209e 146 location: Location) {
ea8adc8c
XL
147 if *local == self.query {
148 (self.callback)(local, context, location)
9e0c209e
SL
149 }
150 }
151}